Python-pandas-时间序列
2026/8/4 8:51:47 网站建设 项目流程

Pandas 时间序列

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


📅 日期时间类型

pd.Timestamp— 单个时间点

importpandasaspdimportnumpyasnp# 创建 Timestampts=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)# 2024print(ts.month)# 7print(ts.day)# 15print(ts.hour)# 14print(ts.minute)# 30print(ts.second)# 0print(ts.dayofweek)# 0 (周一=0, 周日=6)print(ts.dayofyear)# 197print(ts.quarter)# 3print(ts.week)# 29print(ts.days_in_month)# 31print(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— 时间差

# 创建 Timedeltadelta=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-22print(ts-pd.Timedelta(weeks=2))# 2024-07-01print(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# 周一=0df['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(lambdax: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(lambdax: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

frompandas.tseries.offsetsimportDay,MonthEnd,YearEnd,BDay ts=pd.Timestamp('2024-07-15')print(ts+Day(1))# 2024-07-16print(ts+MonthEnd())# 2024-07-31print(ts+BDay(5))# 5 个工作日后的日期print(ts+pd.DateOffset(months=3))# 3 个月后print(ts+pd.DateOffset(years=1,days=-1))# 一年差一天# 生成偏移序列frompandas.tseries.offsetsimportMonthEnd pd.date_range('2024-01-31',periods=12,freq=MonthEnd())

[[pandas2-总览|← 返回总览]]

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询