pandas之处理时间序列数据

一、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.strptimeparse不能):

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
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
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值