irpas技术客

pandas之处理时间序列数据_诡秘愚者_pandas时间序列处理

未知 1014

文章目录 一、datetime库1. 字符串与datetime相互转换 二、pandas中的时间序列数据1. to_datetime方法2. 作为索引2.1 短的序列2.2 长的序列2.3 含有重复索引的序列 3. 日期范围、频率和移位3.1 生成日期范围3.2 移位 4. 重新采样与频率转换4.1 下采样

一、datetime库

datetime库中有以下几种类型:

from datetime import datetime from datetime import timedelta 1. 字符串与datetime相互转换

datetime转换为字符串:

stamp = datetime(2022, 4, 8) str(stamp) # 结果:'2022-04-08 00:00:00' stamp.strftime('%Y-%m-%d') # 结果:'2022-04-08'

将字符串转化为datetime:

datetime.strptime是在已知格式的情况下转换日期的好方式:

s = '2022-04-09' datetime.strptime(s, '%Y-%m-%d') # 结果:datetime.datetime(2022, 4, 9, 0, 0)

每次都必须编写一个格式代码可能有点烦人,特别是对于通用日期格式。在这种情况下,你可以使用第三方dateutil包的parser.parse方法(这个包在安装pandas时已经自动安装,所以不需额外安装):

from dateutil.parser import parse s = '2022-04-09' parse(s) # 结果:datetime.datetime(2022, 4, 9, 0, 0)

dateutil能够解析大部分人类可理解的日期表示:

parse('Jan 31, 2022 10:45 PM') # 结果:datetime.datetime(2022, 1, 31, 22, 45)

如果日期出现在月份之前,可以传递dayfirst=True来表明这种情况:

parse('9/4/2022', dayfirst=True) # 结果:datetime.datetime(2022, 4, 9, 0, 0) 二、pandas中的时间序列数据 1. to_datetime方法

pandas中的to_datetime方法可以转换很多不同的日期表示格式:

s = '2022-04-09' pd.to_datetime(s) # 结果:Timestamp('2022-04-09 00:00:00')

同时转换多个日期,即传入列表(datetime.strptime和parse不能):

dates = ['2022-04-01', '2022-04-03','2022-04-05','2022-04-07','2022-04-09'] pd.to_datetime(dates) # 结果:DatetimeIndex(['2022-04-01', '2022-04-03', '2022-04-05', '2022-04-07', '2022-04-09'], dtype='datetime64[ns]', freq=None)

to_datetime方法生成的是Timestamp对象。

同样的,也可以传递dayfirst=True。

参考pandas中的to_datetime()方法

另外,to_datetime方法还可以处理那些被认为是缺失值的值:

dt = ['2022-04-09', '2022-04-10', None] pd.to_datetime(dt) # 结果:DatetimeIndex(['2022-04-09', '2022-04-10', 'NaT'], dtype='datetime64[ns]', freq=None)

其中,NaT(Not a time)是pandas中时间戳数据的是null值。

2. 作为索引

时间序列数据可作为series和dataframe的索引,以Series为例。

2.1 短的序列 dates = pd.to_datetime(['2022-04-01', '2022-04-03','2022-04-05','2022-04-07','2022-04-09']) ds = pd.Series(np.random.uniform(0, 1, 5), index=dates)

ds:

2022-04-01 0.089425 2022-04-03 0.917701 2022-04-05 0.222676 2022-04-07 0.450355 2022-04-09 0.125723 dtype: float64 可以像普通的Series一样进行选择: ds[1] # 结果:0.9177005610779598 也可以传入相应的时间序列数据: ds['2022-04-03'] # 结果:0.9177005610779598 还可以传递一个能解释为日期的字符串: ds['2022/04/03'] # 结果:0.9177005610779598 2.2 长的序列 longer_ds = pd.Series(data=np.random.uniform(0, 1, 1000), index=pd.date_range('2022-01-01', periods=1000))

pandas 时间序列之pd.date_range()

longer_ds:

2022-01-01 0.807610 2022-01-02 0.559262 2022-01-03 0.216209 2022-01-04 0.577930 2022-01-05 0.674460 ... 2024-09-22 0.407143 2024-09-23 0.730174 2024-09-24 0.803955 2024-09-25 0.647067 2024-09-26 0.338940 Freq: D, Length: 1000, dtype: float64 可以传递一个年份来选择数据: longer_ds['2022']

输出结果:

2022-01-01 0.807610 2022-01-02 0.559262 2022-01-03 0.216209 2022-01-04 0.577930 2022-01-05 0.674460 ... 2022-12-27 0.000907 2022-12-28 0.532692 2022-12-29 0.765496 2022-12-30 0.319450 2022-12-31 0.746440 Freq: D, Length: 365, dtype: float64

这里的字符串'2022'被解释为了年份。

也可以传递年份+月份,但不能仅传递月份: longer_ds['2022-04']

输出结果:

2022-04-01 0.050926 2022-04-02 0.442934 2022-04-03 0.753951 2022-04-04 0.069381 2022-04-05 0.136684 ... 2022-04-25 0.585125 2022-04-26 0.612559 2022-04-27 0.180499 2022-04-28 0.184621 2022-04-29 0.614060 2022-04-30 0.778345 Freq: D, dtype: float64? 也可以传递datetime对象: longer_ds[datetime(2022, 1 , 1)] # 结果:0.8076095055689887 使用truncate方法: 使用truncate时的索引必须先进行排序,不然会报错 详见:Python pandas.DataFrame.truncate函数方法的使用 longer_ds.truncate(after='2022-04-01')

输出结果:

2022-01-01 0.807610 2022-01-02 0.559262 2022-01-03 0.216209 2022-01-04 0.577930 2022-01-05 0.674460 ... 2022-03-28 0.303901 2022-03-29 0.892455 2022-03-30 0.206263 2022-03-31 0.899058 2022-04-01 0.050926 Freq: D, Length: 91, dtype: float64 2.3 含有重复索引的序列 dates = pd.to_datetime(['2022-01-01', '2022-01-01', '2022-01-03', '2022-01-03', '2022-01-05']) ds = pd.Series(np.random.uniform(0, 1, 5), index=dates)

ds:

2022-01-01 0.905035 2022-01-01 0.486505 2022-01-03 0.707109 2022-01-03 0.016314 2022-01-05 0.554270 dtype: float64

可以通过索引的is_unique属性查看索引是否含有重复值:

ds.index.is_unique # 结果:False ds['2022-01-05'] # 结果:0.5542699289639651,为标量指 ds['2022-01-01']

输出结果:

2022-01-01 0.905035 2022-01-01 0.486505 dtype: float64

结果为Series切片。

3. 日期范围、频率和移位 3.1 生成日期范围

pandas.date_range可用于根据特定频率生成指定长度的DatetimeIndex,默认情况下,date_range生成的是每日的时间戳:

index = pd.date_range(start='2022-04-01', end='2022-04-30')

index:

DatetimeIndex(['2022-04-01', '2022-04-02', '2022-04-03', '2022-04-04', '2022-04-05', '2022-04-06', '2022-04-07', '2022-04-08', '2022-04-09', '2022-04-10', '2022-04-11', '2022-04-12', '2022-04-13', '2022-04-14', '2022-04-15', '2022-04-16', '2022-04-17', '2022-04-18', '2022-04-19', '2022-04-20', '2022-04-21', '2022-04-22', '2022-04-23', '2022-04-24', '2022-04-25', '2022-04-26', '2022-04-27', '2022-04-28', '2022-04-29', '2022-04-30'], dtype='datetime64[ns]', freq='D') ? 如果只传递一个起始或结尾日期,必须传递一个用于生成范围的数字: index = pd.date_range(start='2022-04-01', periods=30)

index:

DatetimeIndex(['2022-04-01', '2022-04-02', '2022-04-03', '2022-04-04', '2022-04-05', '2022-04-06', '2022-04-07', '2022-04-08', '2022-04-09', '2022-04-10', '2022-04-11', '2022-04-12', '2022-04-13', '2022-04-14', '2022-04-15', '2022-04-16', '2022-04-17', '2022-04-18', '2022-04-19', '2022-04-20', '2022-04-21', '2022-04-22', '2022-04-23', '2022-04-24', '2022-04-25', '2022-04-26', '2022-04-27', '2022-04-28', '2022-04-29', '2022-04-30'], dtype='datetime64[ns]', freq='D') ? 特殊的频率,比如需要一个包含每月最后业务日期的时间索引: index = pd.date_range(start='2022-01-01', end='2022-12-01', freq='BM')

index:

DatetimeIndex(['2022-01-31', '2022-02-28', '2022-03-31', '2022-04-29', '2022-05-31', '2022-06-30', '2022-07-29', '2022-08-31', '2022-09-30', '2022-10-31', '2022-11-30'], dtype='datetime64[ns]', freq='BM') ?

固定间隔: index = pd.date_range(start='2022-04-01', end='2022-04-07', freq='4h')

index:

DatetimeIndex(['2022-04-01 00:00:00', '2022-04-01 04:00:00', '2022-04-01 08:00:00', '2022-04-01 12:00:00', '2022-04-01 16:00:00', '2022-04-01 20:00:00', '2022-04-02 00:00:00', '2022-04-02 04:00:00', '2022-04-02 08:00:00', '2022-04-02 12:00:00', '2022-04-02 16:00:00', '2022-04-02 20:00:00', '2022-04-03 00:00:00', '2022-04-03 04:00:00', '2022-04-03 08:00:00', '2022-04-03 12:00:00', '2022-04-03 16:00:00', '2022-04-03 20:00:00', '2022-04-04 00:00:00', '2022-04-04 04:00:00', '2022-04-04 08:00:00', '2022-04-04 12:00:00', '2022-04-04 16:00:00', '2022-04-04 20:00:00', '2022-04-05 00:00:00', '2022-04-05 04:00:00', '2022-04-05 08:00:00', '2022-04-05 12:00:00', '2022-04-05 16:00:00', '2022-04-05 20:00:00', '2022-04-06 00:00:00', '2022-04-06 04:00:00', '2022-04-06 08:00:00', '2022-04-06 12:00:00', '2022-04-06 16:00:00', '2022-04-06 20:00:00', '2022-04-07 00:00:00'], dtype='datetime64[ns]', freq='4H') 生成的是标准化为零点的时间戳: index = pd.date_range(start='2022-04-01 10:23:42', periods=7, normalize=True)

index:

DatetimeIndex(['2022-04-01', '2022-04-02', '2022-04-03', '2022-04-04', '2022-04-05', '2022-04-06', '2022-04-07'], dtype='datetime64[ns]', freq='D') 3.2 移位

移位"是指将日期按时间向前移动或向后移动。Series和DataFrame都有一个shift方法用于简单的前向或后向移位,而不改变索引:

ds = pd.Series(data=np.random.randn(5), index=pd.date_range(start='2022-04-01', periods=5))

ds:

2022-04-01 0.169925 2022-04-02 -0.178289 2022-04-03 0.181091 2022-04-04 -0.373990 2022-04-05 0.060268 Freq: D, dtype: float64

前向移位:

ds.shift(2)

输出结果:

2022-04-01 NaN 2022-04-02 NaN 2022-04-03 0.169925 2022-04-04 -0.178289 2022-04-05 0.181091 Freq: D, dtype: float64

后向移位:

ds.shift(-2)

输出结果:

2022-04-01 0.181091 2022-04-02 -0.373990 2022-04-03 0.060268 2022-04-04 NaN 2022-04-05 NaN Freq: D, dtype: float64 4. 重新采样与频率转换

重新采样是指将时间序列从一个频率转换为另一个频率的过程。将更高频率的数据聚合到低频率被称为向下采样,而从低频率转换到高频率称为向上采样。并不是所有的重新采样都属于上面说的两类;例如,将W-WED(weekly onWednesday,每周三)转换到W-FRI(每周五)既不是向上采样也不是向下采样。

可先调用resample对数据分组,之后再调用聚合函数:

ds = pd.Series(data=np.random.randn(100), index=pd.date_range(start='2022-01-01', periods=100))

ds:

2022-01-01 -2.884805 2022-01-02 0.786080 2022-01-03 -1.191273 2022-01-04 0.468861 2022-01-05 0.462229 ... 2022-04-06 0.753766 2022-04-07 0.827008 2022-04-08 -0.193957 2022-04-09 1.098543 2022-04-10 1.593474 Freq: D, Length: 100, dtype: float64 ds.resample('M').mean()

输出结果:

2022-01-31 -0.025061 2022-02-28 0.302152 2022-03-31 0.209327 2022-04-30 0.599747 Freq: M, dtype: float64

resample方法参数:

4.1 下采样

使用resample进行向下采样数据时有些事情需要考虑:

每段间隔的哪一边是闭合的如何在间隔的起始或结束位置标记每个已聚合的箱体

以分钟维度的数据为例:

ds = pd.Series(data=np.arange(12), index=pd.date_range(start='2022-01-01', periods=12, freq='T'))

ds:

2022-01-01 00:00:00 0 2022-01-01 00:01:00 1 2022-01-01 00:02:00 2 2022-01-01 00:03:00 3 2022-01-01 00:04:00 4 2022-01-01 00:05:00 5 2022-01-01 00:06:00 6 2022-01-01 00:07:00 7 2022-01-01 00:08:00 8 2022-01-01 00:09:00 9 2022-01-01 00:10:00 10 2022-01-01 00:11:00 11 Freq: T, dtype: int32

计算5分钟的和:

ds.resample('5min', closed='right', label='right').sum()

输出结果:

2022-01-01 00:00:00 0 2022-01-01 00:05:00 15 2022-01-01 00:10:00 40 2022-01-01 00:15:00 11 Freq: 5T, dtype: int32

可以将结果索引移动一定的数量,例如从右边缘减去一秒,以使其更清楚地表明时间戳所指的间隔:

ds.resample('5min', closed='right', label='right', loffset='-1s').sum()

结果输出:

2021-12-31 23:59:59 0 2022-01-01 00:04:59 15 2022-01-01 00:09:59 40 2022-01-01 00:14:59 11 Freq: 5T, dtype: int32

为每个桶计算第一个值(开端)、最后一个值(结束)、最大值(峰值)和最小值(谷值):

ds.resample('5min', closed='right', label='right', loffset='-1s').ohlc()

输出结果:

open high low close 2021-12-31 23:59:59 0 0 0 0 2022-01-01 00:04:59 1 5 1 5 2022-01-01 00:09:59 6 10 6 10 2022-01-01 00:14:59 11 11 11 11


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #pandas时间序列处理 #pandas中的时间序列数据