当前位置: 代码网 > it编程>前端脚本>Python > Pandas时间序列怎么处理?日期解析与重采样方法详解

Pandas时间序列怎么处理?日期解析与重采样方法详解

2026年08月05日 Python 我要评论
pandas 拥有强大的时间序列处理能力,涵盖日期解析、重采样、滚动窗口、时区处理等。日期时间类型pd.timestamp— 单个时间点import pandas as pdimport

pandas 拥有强大的时间序列处理能力,涵盖日期解析、重采样、滚动窗口、时区处理等。

日期时间类型

pd.timestamp— 单个时间点

import pandas as pd
import numpy as np

# 创建 timestamp
ts = pd.timestamp('2024-07-15')
ts = pd.timestamp('2024-07-15 14:30:00')
ts = pd.timestamp('2024-07-15 14:30:00+08:00')  # 带时区
ts = pd.timestamp.now()          # 当前时间
ts = pd.timestamp.now(tz='asia/shanghai')
ts = pd.timestamp(year=2024, month=7, day=15, hour=14, minute=30)

# timestamp 属性
print(ts.year)        # 2024
print(ts.month)       # 7
print(ts.day)         # 15
print(ts.hour)        # 14
print(ts.minute)      # 30
print(ts.second)      # 0
print(ts.dayofweek)   # 0 (周一=0, 周日=6)
print(ts.dayofyear)   # 197
print(ts.quarter)     # 3
print(ts.week)        # 29
print(ts.days_in_month)  # 31
print(ts.is_leap_year)   # true (2024 是闰年)

pd.datetimeindex— 时间索引

# 从字符串列表创建
dates = pd.datetimeindex(['2024-01-01', '2024-01-02', '2024-01-03'])

# pd.date_range() — 生成日期范围 ⭐
dates = pd.date_range(start='2024-01-01', end='2024-12-31', freq='d')     # 每天
dates = pd.date_range(start='2024-01-01', periods=12, freq='ms')          # 每月初,12 期
dates = pd.date_range(start='2024-01-01', periods=8, freq='q')            # 每季末,8 期
dates = pd.date_range(start='2024-01-01', periods=52, freq='w-mon')       # 每周一
dates = pd.date_range(start='2024-01-01', periods=5, freq='b')            # 工作日
dates = pd.date_range(start='2024-01-01 09:00', periods=8, freq='h')      # 每小时
dates = pd.date_range(start='2024-01-01', periods=96, freq='15min')       # 每 15 分钟

# 常用频率别名
# 'd'  日历日       'b'  工作日       'w'  周日结束的周
# 'm'  月末          'ms' 月初         'q'  季末
# 'qs' 季初         'y'  年末         'ys' 年初
# 'h'  小时          'min' 分钟        's'  秒
# 'w-mon' 周一结束  'bms' 月初工作日

pd.timedelta— 时间差

# 创建 timedelta
delta = pd.timedelta(days=1)
delta = pd.timedelta('1 day')
delta = pd.timedelta('2 days 3 hours 30 minutes')
delta = pd.timedelta('1w')      # 1 周
delta = pd.timedelta('3d 5h')   # 3 天 5 小时

# 时间运算
ts = pd.timestamp('2024-07-15')
print(ts + pd.timedelta(days=7))    # 2024-07-22
print(ts - pd.timedelta(weeks=2))   # 2024-07-01
print(ts + pd.timedelta(hours=48))  # 2024-07-17 00:00:00

解析与转换

pd.to_datetime()— 字符串转时间

# 基本转换
s = pd.series(['2024-01-01', '2024-01-02', 'invalid', '2024-01-04'])
dates = pd.to_datetime(s, errors='coerce')  # 无效值 -> nat

# errors 选项
# 'raise': 遇到无效值报错(默认)
# 'coerce': 无效值转为 nat
# 'ignore': 无效值保持原样

# 指定格式(加速解析)
dates = pd.to_datetime(s, format='%y-%m-%d')

# 常用格式码
# %y  四位年份        %y  两位年份        %m  月份(01-12)
# %d  日期(01-31)     %h  时(00-23)       %m  分(00-59)
# %s  秒(00-59)       %f  微秒             %z  utc偏移
# %b  英文缩写月份     %a  星期全称         %a  星期缩写

# 推断格式
dates = pd.to_datetime(s, infer_datetime_format=true)  # 自动推断

以时间为索引的 dataframe

# 创建时间索引
dates = pd.date_range('2024-01-01', periods=365, freq='d')
df = pd.dataframe({
    'sales': np.random.randn(365).cumsum() + 100,
    'visitors': np.random.randint(100, 500, 365) + np.arange(365)
}, index=dates)

# 按时间切片
df['2024-01']         # 2024 年 1 月所有数据
df['2024-01-15']      # 1 月 15 日
df['2024-01':'2024-03']  # 1 月到 3 月
df['2024-01-15':'2024-02-15']  # 跨时间段

# 时间属性访问
df['year'] = df.index.year
df['month'] = df.index.month
df['day'] = df.index.day
df['weekday'] = df.index.weekday   # 周一=0
df['quarter'] = df.index.quarter
df['day_name'] = df.index.day_name()  # 'monday', 'tuesday'...
df['is_month_start'] = df.index.is_month_start
df['is_quarter_end'] = df.index.is_quarter_end

between_time()— 按时间段筛选

# 创建带时间戳的数据
idx = pd.date_range('2024-01-01', periods=96, freq='15min')
ts = pd.series(range(96), index=idx)

# 筛选 09:00 - 17:00 的数据
ts.between_time('09:00', '17:00')

# 筛选非工作时间
ts.between_time('17:00', '09:00', include_start=false)

重采样resample()

将时间序列从一种频率转换到另一种频率。

dates = pd.date_range('2024-01-01', periods=365, freq='d')
df = pd.dataframe({
    'value': np.random.randn(365).cumsum()
}, index=dates)

# 降采样: 日 -> 月
monthly = df.resample('m')['value'].mean()     # 月均值
monthly = df.resample('m')['value'].sum()      # 月总和
monthly = df.resample('m')['value'].last()     # 月末值
monthly = df.resample('m')['value'].first()    # 月初值
monthly = df.resample('m')['value'].ohlc()     # open/high/low/close

# 升采样: 日 -> 小时(需要填充)
hourly = df.resample('h').ffill()      # 前向填充
hourly = df.resample('h').bfill()      # 后向填充
hourly = df.resample('h').interpolate()  # 插值
hourly = df.resample('h').asfreq()       # 不填充(nan)

# 多列聚合
result = df.resample('w').agg({
    'sales': 'sum',
    'visitors': 'mean'
})

# 自定义聚合
result = df.resample('m').apply(lambda x: x.max() - x.min())

resample常用频率

频率含义频率含义
'd'日历日'w'周(周日结束)
'm'月末'ms'月初
'q'季末'qs'季初
'y' / 'a'年末'ys' / 'as'年初
'h' / 'h'小时'min' / 't'分钟
'w-mon'周一结束'b'工作日
'sm'半月(15日+月末)'bm'工作月末
'q-dec'12月结束的季'bq'工作季末

滚动窗口rolling()

df = pd.dataframe({
    'price': np.random.randn(252).cumsum() + 100
}, index=pd.date_range('2024-01-01', periods=252, freq='b'))

# 简单移动平均
df['sma_7'] = df['price'].rolling(window=7).mean()
df['sma_30'] = df['price'].rolling(window=30).mean()

# 其他滚动统计
df['rolling_std'] = df['price'].rolling(7).std()       # 滚动标准差
df['rolling_min'] = df['price'].rolling(7).min()       # 滚动最小值
df['rolling_max'] = df['price'].rolling(7).max()       # 滚动最大值
df['rolling_sum'] = df['price'].rolling(7).sum()       # 滚动求和
df['rolling_median'] = df['price'].rolling(7).median()  # 滚动中位数
df['rolling_quantile'] = df['price'].rolling(30).quantile(0.9)  # 滚动分位数
df['rolling_skew'] = df['price'].rolling(30).skew()    # 滚动偏度
df['rolling_corr'] = df['price'].rolling(30).corr(df['price'].shift())  # 滚动相关

# 自定义滚动函数
df['rolling_range'] = df['price'].rolling(7).apply(
    lambda x: x.max() - x.min()
)

# rolling 参数
# window: 窗口大小(int 或 offset 如 '7d')
# min_periods: 最少非空观测数
# center: 标签是否居中(默认 false)
# win_type: 窗口类型 (如 'gaussian', 'triang')
# closed: 区间闭合方式 ('right'/'left'/'both'/'neither')

时间偏移窗口

# 按时间而非行数的滚动窗口(索引必须是 datetimeindex)
df['rolling_7d'] = df['price'].rolling(window='7d').mean()

# 支持的时间窗口
df['price'].rolling(window='3d').mean()
df['price'].rolling(window='2h').mean()
df['price'].rolling(window='30min').mean()

expanding()— 扩展窗口

从序列开始累积到当前,窗口越来越大。

# 累积统计
df['expanding_mean'] = df['price'].expanding().mean()
df['expanding_std'] = df['price'].expanding().std()
df['expanding_max'] = df['price'].expanding().max()

# 最小观测数
df['expanding_mean_min10'] = df['price'].expanding(min_periods=10).mean()

ewm()— 指数加权

# 指数加权移动平均
df['ewm_alpha'] = df['price'].ewm(alpha=0.3).mean()       # 平滑因子 α
df['ewm_span'] = df['price'].ewm(span=7).mean()           # 跨度(相当于 7 天 sma)
df['ewm_halflife'] = df['price'].ewm(halflife=3).mean()   # 半衰期
df['ewm_com'] = df['price'].ewm(com=3.5).mean()           # 质心

# 其他 ewm 统计
df['ewm_std'] = df['price'].ewm(span=7).std()
df['ewm_var'] = df['price'].ewm(span=7).var()
df['ewm_corr'] = df['price'].ewm(span=7).corr(df['price'].shift())

shift()/diff()/pct_change()

# shift: 平移
df['price_lag1'] = df['price'].shift(1)       # 前移 1 期
df['price_lead1'] = df['price'].shift(-1)     # 后移 1 期
df['price_lag7'] = df['price'].shift(7)       # 前移 7 期

# 按频率平移(索引必须是 datetimeindex)
df['price_1m_ago'] = df['price'].shift(periods=1, freq='m')

# diff: 差分
df['price_diff'] = df['price'].diff()         # 一阶差分
df['price_diff2'] = df['price'].diff(2)       # 二阶差分

# pct_change: 变化率
df['returns'] = df['price'].pct_change()              # 日变化率
df['weekly_return'] = df['price'].pct_change(periods=5)  # 周变化率

时区处理

# 本地化时区
ts = pd.timestamp('2024-07-15 14:30:00')
ts_beijing = ts.tz_localize('asia/shanghai')
# timestamp('2024-07-15 14:30:00+0800')

# 时区转换
ts_ny = ts_beijing.tz_convert('america/new_york')
# timestamp('2024-07-15 02:30:00-0400')

# dataframe 时区操作
idx = pd.date_range('2024-01-01', periods=10, freq='d')
df = pd.dataframe({'val': range(10)}, index=idx)

df = df.tz_localize('asia/shanghai')       # 添加时区
df = df.tz_convert('utc')                  # 转时区
df = df.tz_localize(none)                  # 移除时区(不转换时间)

# 常用时区
# 'asia/shanghai'   中国标准时间 (utc+8)
# 'asia/tokyo'      日本标准时间 (utc+9)
# 'america/new_york' 美东 (utc-5/-4)
# 'europe/london'   英国 (utc+0/+1)
# 'utc' / 'etc/gmt' 世界协调时

时间偏移pd.dateoffset

from pandas.tseries.offsets import day, monthend, yearend, bday

ts = pd.timestamp('2024-07-15')
print(ts + day(1))           # 2024-07-16
print(ts + monthend())       # 2024-07-31
print(ts + bday(5))          # 5 个工作日后的日期
print(ts + pd.dateoffset(months=3))     # 3 个月后
print(ts + pd.dateoffset(years=1, days=-1))  # 一年差一天

# 生成偏移序列
from pandas.tseries.offsets import monthend
pd.date_range('2024-01-31', periods=12, freq=monthend())

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com