Pandas-之时间序列处理
时间序列处理
目录
- 时间戳和 DatetimeIndex
- 创建时间序列
- 时间索引选择
- 时间重采样
- 时间偏移和频率
- 时间序列计算
- 实际应用示例
时间戳和 DatetimeIndex
创建时间戳
import pandas as pd
from datetime import datetime# 创建单个时间戳
ts = pd.Timestamp('2024-01-01')
print(ts) # 2024-01-01 00:00:00# 使用 datetime 对象
ts = pd.Timestamp(datetime(2024, 1, 1, 12, 30, 45))
print(ts)# 指定时区
ts = pd.Timestamp('2024-01-01', tz='Asia/Shanghai')
print(ts)# 获取时间属性
ts = pd.Timestamp('2024-01-15 14:30:00')
print(f"年份: {ts.year}")
print(f"月份: {ts.month}")
print(f"日期: {ts.day}")
print(f"小时: {ts.hour}")
print(f"分钟: {ts.minute}")
print(f"星期几: {ts.dayofweek}") # 0=Monday
print(f"一年中的第几天: {ts.dayofyear}")
DatetimeIndex
import pandas as pd# 创建 DatetimeIndex
dates = pd.date_range('2024-01-01', periods=10, freq='D')
print(dates)
# 输出:
# DatetimeIndex(['2024-01-01', '2024-01-02', ..., '2024-01-10'],
# dtype='datetime64[ns]', freq='D')# 从字符串列表创建
date_strings = ['2024-01-01', '2024-01-02', '2024-01-03']
dates = pd.to_datetime(date_strings)
print(dates)# 创建 DataFrame 并使用时间索引
df = pd.DataFrame({'value': range(10)
}, index=dates)
print(df)
创建时间序列
使用 date_range
import pandas as pd# 基本用法
dates = pd.date_range('2024-01-01', periods=10, freq='D')
print(dates)# 指定结束日期
dates = pd.date_range('2024-01-01', '2024-01-10', freq='D')
print(dates)# 不同频率
daily = pd.date_range('2024-01-01', periods=10, freq='D')
weekly = pd.date_range('2024-01-01', periods=10, freq='W')
monthly = pd.date_range('2024-01-01', periods=10, freq='M')
yearly = pd.date_range('2024-01-01', periods=10, freq='Y')print(f"日频率: {daily[:3]}")
print(f"周频率: {weekly[:3]}")
print(f"月频率: {monthly[:3]}")
print(f"年频率: {yearly[:3]}")# 工作日频率
business_days = pd.date_range('2024-01-01', periods=10, freq='B')
print(f"工作日: {business_days[:5]}")# 小时频率
hourly = pd.date_range('2024-01-01', periods=24, freq='H')
print(f"小时频率: {hourly[:5]}")
使用 to_datetime
import pandas as pd# 从字符串转换
dates = pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-03'])
print(dates)# 从 DataFrame 列转换
df = pd.DataFrame({'date': ['2024-01-01', '2024-01-02', '2024-01-03'],'value': [1, 2, 3]
})
df['date'] = pd.to_datetime(df['date'])
print(df.dtypes)# 处理多种日期格式
dates_mixed = ['2024-01-01', '01/02/2024', '2024-01-03']
dates = pd.to_datetime(dates_mixed)
print(dates)# 处理错误(coerce 将错误值转为 NaT)
dates_with_errors = ['2024-01-01', 'invalid', '2024-01-03']
dates = pd.to_datetime(dates_with_errors, errors='coerce')
print(dates)
创建时间序列 DataFrame
import pandas as pd
import numpy as np# 创建时间序列数据
dates = pd.date_range('2024-01-01', periods=100, freq='D')
df = pd.DataFrame({'日期': dates,'价格': np.random.uniform(10, 20, 100),'成交量': np.random.randint(1000, 5000, 100)
})# 将日期设为索引
df.set_index('日期', inplace=True)
print(df.head())# 或者直接创建带时间索引的 DataFrame
df = pd.DataFrame({'价格': np.random.uniform(10, 20, 100),'成交量': np.random.randint(1000, 5000, 100)
}, index=pd.date_range('2024-01-01', periods=100, freq='D'))
print(df.head())
时间索引选择
import pandas as pd
import numpy as np# 创建时间序列数据
dates = pd.date_range('2024-01-01', periods=365, freq='D')
df = pd.DataFrame({'价格': np.random.uniform(10, 20, 365),'成交量': np.random.randint(1000, 5000, 365)
}, index=dates)# 按日期选择
print(df.loc['2024-01-01'])# 按日期范围选择
print(df.loc['2024-01-01':'2024-01-10'])# 按月份选择
print(df.loc['2024-01'])# 按年份选择
print(df.loc['2024'])# 使用 partial string indexing
print(df['2024-01-01':'2024-01-31'])# 使用 datetime 对象
from datetime import datetime
start = datetime(2024, 1, 1)
end = datetime(2024, 1, 31)
print(df.loc[start:end])
时间重采样
重采样是时间序列分析的重要操作,可以改变数据的频率。
基本重采样
import pandas as pd
import numpy as np# 创建日数据
dates = pd.date_range('2024-01-01', periods=90, freq='D')
df = pd.DataFrame({'价格': np.random.uniform(10, 20, 90),'成交量': np.random.randint(1000, 5000, 90)
}, index=dates)# 重采样为周(默认聚合函数为 mean)
weekly = df.resample('W').mean()
print("周数据:")
print(weekly.head())# 重采样为月
monthly = df.resample('M').mean()
print("\n月数据:")
print(monthly)# 使用不同的聚合函数
weekly_sum = df.resample('W').sum()
weekly_max = df.resample('W').max()
weekly_min = df.resample('W').min()print("\n周汇总:")
print(weekly_sum.head())# 多列使用不同聚合函数
result = df.resample('W').agg({'价格': 'mean','成交量': 'sum'
})
print("\n周聚合(不同函数):")
print(result.head())
高级重采样
import pandas as pd
import numpy as npdates = pd.date_range('2024-01-01', periods=90, freq='D')
df = pd.DataFrame({'价格': np.random.uniform(10, 20, 90)
}, index=dates)# 上采样(增加频率):日数据转小时数据
hourly = df.resample('H').asfreq() # 填充 NaN
hourly_interpolated = df.resample('H').interpolate() # 插值
hourly_ffill = df.resample('H').ffill() # 前向填充
hourly_bfill = df.resample('H').bfill() # 后向填充# 使用 origin 参数
weekly = df.resample('W', origin='2024-01-01').sum()# 使用 label 参数(标签位置)
weekly_left = df.resample('W', label='left').sum() # 标签在区间开始
weekly_right = df.resample('W', label='right').sum() # 标签在区间结束
时间偏移和频率
频率字符串
import pandas as pd# 常见频率
frequencies = {'D': '日','B': '工作日','W': '周','M': '月末','Q': '季末','A': '年末','H': '小时','T': '分钟','S': '秒'
}# 创建不同频率的索引
for freq, desc in list(frequencies.items())[:5]:dates = pd.date_range('2024-01-01', periods=5, freq=freq)print(f"{desc} ({freq}): {dates}")
时间偏移
import pandas as pd
from pandas.tseries.offsets import Day, MonthEnd, YearEnd# 创建时间戳
ts = pd.Timestamp('2024-01-15')# 添加偏移
print(f"原始日期: {ts}")
print(f"加1天: {ts + Day(1)}")
print(f"加1个月: {ts + MonthEnd(1)}")
print(f"加1年: {ts + YearEnd(1)}")# 在 DataFrame 中使用
dates = pd.date_range('2024-01-01', periods=10, freq='D')
df = pd.DataFrame({'日期': dates, '值': range(10)})
df['下一天'] = df['日期'] + Day(1)
df['下个月'] = df['日期'] + MonthEnd(1)
print(df)
时间周期
import pandas as pd# Period(时间段)
period = pd.Period('2024-01')
print(period) # 2024-01
print(period.start_time) # 2024-01-01 00:00:00
print(period.end_time) # 2024-01-31 23:59:59.999999999# PeriodIndex
periods = pd.period_range('2024-01', periods=12, freq='M')
print(periods)# 在 DataFrame 中使用
df = pd.DataFrame({'月份': periods,'销售额': range(12)
})
print(df)
时间序列计算
时间差计算
import pandas as pddates = pd.date_range('2024-01-01', periods=10, freq='D')
df = pd.DataFrame({'日期': dates,'值': range(10)
})# 计算时间差
df['天数差'] = df['日期'].diff()
print(df)# 计算相对于第一个日期的天数
df['距起始天数'] = (df['日期'] - df['日期'].iloc[0]).dt.days
print(df)# 计算工作日数
from pandas.tseries.offsets import BDay
df['距起始工作日'] = (df['日期'] - df['日期'].iloc[0]) // BDay(1)
print(df)
滚动窗口计算
import pandas as pd
import numpy as npdates = pd.date_range('2024-01-01', periods=100, freq='D')
df = pd.DataFrame({'价格': np.random.uniform(10, 20, 100)
}, index=dates)# 滚动平均(7天)
df['7日均价'] = df['价格'].rolling(window=7).mean()
print(df.head(10))# 滚动总和
df['7日累计'] = df['价格'].rolling(window=7).sum()# 滚动最大值和最小值
df['7日最高'] = df['价格'].rolling(window=7).max()
df['7日最低'] = df['价格'].rolling(window=7).min()# 滚动标准差
df['7日标准差'] = df['价格'].rolling(window=7).std()print(df.head(10))# 扩展窗口(累积统计)
df['累积平均'] = df['价格'].expanding().mean()
df['累积总和'] = df['价格'].expanding().sum()
时间序列统计
import pandas as pd
import numpy as npdates = pd.date_range('2024-01-01', periods=365, freq='D')
df = pd.DataFrame({'价格': np.random.uniform(10, 20, 365)
}, index=dates)# 年度统计
yearly_stats = df.resample('A').agg(['mean', 'std', 'min', 'max'])
print("年度统计:")
print(yearly_stats)# 月度统计
monthly_stats = df.resample('M').agg(['mean', 'std'])
print("\n月度统计:")
print(monthly_stats.head())# 计算同比增长
df['月份'] = df.index.to_period('M')
monthly = df.groupby('月份')['价格'].mean()
monthly['同比增长'] = monthly.pct_change(periods=12) * 100 # 假设有多年数据
实际应用示例
示例 1:股票价格分析
import pandas as pd
import numpy as np# 创建股票价格数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=252, freq='B') # 交易日
prices = 100 * np.cumprod(1 + np.random.randn(252) * 0.02) # 随机游走df = pd.DataFrame({'收盘价': prices,'成交量': np.random.randint(1000000, 5000000, 252)
}, index=dates)# 计算技术指标
df['5日均线'] = df['收盘价'].rolling(window=5).mean()
df['20日均线'] = df['收盘价'].rolling(window=20).mean()
df['50日均线'] = df['收盘价'].rolling(window=50).mean()# 计算收益率
df['日收益率'] = df['收盘价'].pct_change()
df['累计收益率'] = (1 + df['日收益率']).cumprod() - 1# 计算波动率
df['30日波动率'] = df['日收益率'].rolling(window=30).std() * np.sqrt(252)# 月度统计
monthly = df.resample('M').agg({'收盘价': ['first', 'last', 'mean'],'成交量': 'sum'
})
monthly.columns = ['月初价', '月末价', '月均价', '月成交量']
monthly['月度收益率'] = (monthly['月末价'] / monthly['月初价'] - 1) * 100print("月度统计:")
print(monthly.head())print("\n技术指标(最近10天):")
print(df[['收盘价', '5日均线', '20日均线', '50日均线']].tail(10))
示例 2:销售数据时间分析
import pandas as pd
import numpy as np# 创建销售数据
np.random.seed(42)
dates = pd.date_range('2023-01-01', '2024-12-31', freq='D')
sales = pd.DataFrame({'销售额': np.random.randint(10000, 50000, len(dates)),'订单数': np.random.randint(50, 200, len(dates))
}, index=dates)# 添加趋势和季节性
sales['销售额'] = sales['销售额'] + np.sin(2 * np.pi * sales.index.dayofyear / 365) * 10000# 计算移动平均
sales['7日移动平均'] = sales['销售额'].rolling(window=7).mean()
sales['30日移动平均'] = sales['销售额'].rolling(window=30).mean()# 月度汇总
monthly_sales = sales.resample('M').agg({'销售额': 'sum','订单数': 'sum'
})# 计算环比增长
monthly_sales['环比增长'] = monthly_sales['销售额'].pct_change() * 100# 年度对比(如果有多年数据)
sales['年份'] = sales.index.year
sales['月份'] = sales.index.month
yearly_comparison = sales.groupby(['年份', '月份'])['销售额'].sum().unstack(level=0)print("月度销售额:")
print(monthly_sales.head(12))print("\n年度对比(前6个月):")
print(yearly_comparison.head(6))
总结
时间序列处理是 Pandas 的强大功能:
- 时间戳和索引:Timestamp, DatetimeIndex, Period
- 创建时间序列:date_range, to_datetime
- 时间选择:按日期、月份、年份选择
- 重采样:改变数据频率
- 滚动窗口:移动平均、移动统计
- 时间计算:时间差、周期性分析
