Pandas 中使用 Timestamp 表示单个时间点,DatetimeIndex 作为一系列时间点的索引,以及 Series/DataFrame 中的 datetime64[ns] 类型。
import pandas as pd
import numpy as np
# 创建单个时间戳
ts = pd.Timestamp('2024-01-01 12:30:00')
print(ts)
# 创建日期范围
dates = pd.date_range('2024-01-01', periods=5, freq='D')
print(dates)
# 将列转换为 datetime 类型
df = pd.DataFrame({'date': ['2024-01-01', '2024-01-02', '2024-01-03']})
df['date'] = pd.to_datetime(df['date'])
print(df.dtypes)
pd.date_range()date_range() 是生成时间序列索引的核心函数。
start: 起始时间end: 结束时间periods: 时间点数量freq: 频率(如 'D' 天, 'H' 小时, 'M' 月末, 'B' 工作日)tz: 时区normalize: 是否归一化到午夜pd.date_range('2024-01-01', '2024-01-10', freq='3D')
pd.date_range('2024-01-01', periods=10, freq='H')
pd.date_range('2024-01-01', periods=5, freq='W-MON') # 每周一
将日期列设置为索引,可以享受时间序列的便捷功能。
# 创建带日期的数据
df = pd.DataFrame({
'value': np.random.randn(100)
}, index=pd.date_range('2024-01-01', periods=100, freq='D'))
print(df.head())
# 按年份、月份等切片
print(df['2024-01']) # 一月份数据
print(df['2024-03-01':'2024-03-10']) # 时间区间切片
当 DataFrame 的索引为 DatetimeIndex 时,可以使用字符串进行非常灵活的切片。
# 创建示例
df = pd.DataFrame({'sales': np.random.randint(100, 200, 365)},
index=pd.date_range('2024-01-01', periods=365, freq='D'))
# 切片
print(df['2024-02']) # 整个二月
print(df['2024-03-15':'2024-04-10']) # 区间
print(df['2024-05']) # 五月
# 利用 .loc 进行精确选择
print(df.loc['2024-06-01'])
resample()重采样是将时间序列从一个频率转换到另一个频率的过程,常用于降采样(如日数据转月数据)或升采样(如日数据转小时数据)。
# 降采样:从日数据聚合成月数据总和
monthly = df.resample('M').sum()
print(monthly.head())
# 不同的聚合函数
df.resample('M').mean() # 月平均
df.resample('Q').max() # 季度最大值
df.resample('Y').ohlc() # 年度的 OHLC(开盘、高、低、收盘)
# 升采样:从日数据插值到小时数据
hourly = df.resample('H').asfreq() # 空值填充
hourly = df.resample('H').ffill() # 前向填充
rolling()滑动窗口计算用于计算滚动统计量,如移动平均。
# 7天移动平均
df['rolling_mean_7'] = df['sales'].rolling(window=7).mean()
# 30天移动总和
df['rolling_sum_30'] = df['sales'].rolling(window=30).sum()
# 可以自定义窗口函数
df['rolling_max_14'] = df['sales'].rolling(window=14).max()
print(df.head(20))
# 从 DatetimeIndex 中提取信息
df['year'] = df.index.year
df['month'] = df.index.month
df['day'] = df.index.day
df['dayofweek'] = df.index.dayofweek # 周一=0
df['quarter'] = df.index.quarter
# 对于 Series/DataFrame 的 datetime 列类似
df['date'] = df.index
df['weekday_name'] = df['date'].dt.day_name()
# 滞后(shift)
df['sales_lag1'] = df['sales'].shift(1) # 前一天的值
df['sales_lag7'] = df['sales'].shift(7) # 一周前的值
# 差分(计算相邻差值)
df['sales_diff1'] = df['sales'].diff(1) # 与前一天的差值
df['sales_diff7'] = df['sales'].diff(7) # 与7天前的差值
import pandas as pd
import numpy as np
# 模拟股票数据
dates = pd.date_range('2024-01-01', periods=100, freq='B') # 工作日
stock = pd.DataFrame({
'price': 100 + np.cumsum(np.random.randn(100)), # 随机游走
'volume': np.random.randint(1000, 10000, 100)
}, index=dates)
print("原始数据:")
print(stock.head())
# 1. 重采样:月度最高价和总成交量
monthly_high = stock['price'].resample('M').max()
monthly_volume = stock['volume'].resample('M').sum()
print("\n月度统计:")
print(pd.DataFrame({'high': monthly_high, 'volume': monthly_volume}))
# 2. 计算20日移动平均和20日价格标准差
stock['ma20'] = stock['price'].rolling(window=20).mean()
stock['std20'] = stock['price'].rolling(window=20).std()
# 3. 计算布林带上轨/下轨
stock['upper'] = stock['ma20'] + 2 * stock['std20']
stock['lower'] = stock['ma20'] - 2 * stock['std20']
# 4. 计算每日收益率
stock['return'] = stock['price'].pct_change() # 百分比变化
print("\n技术指标:")
print(stock.tail(10))
tz_localize() 和 tz_convert() 处理。
asfreq() 升采样时,会引入缺失值,需要填充处理。
resample 的 kind='period' 参数。
datetime64 类型,可以用 pd.to_datetime() 转换。set_index)能发挥 Pandas 时间序列的最大威力。