pandas组队学习-Task9 时序数据

目录

1. 学习内容

2. 准备工作

3. 创建时序数据

3.1 时序数据类型

3.2 创建时间点

3.2.1 to_datetime()方法

3.2.2 date_range()方法

3.2.3 bdate_range()方法

3.3 DateOffset对象

3.3.1 DateOffset与Timedelta的区别

4. 时序的索引及属性

4.1 索引切片

4.2 子集索引

4.3 时间点的属性

5. 重采样

5.1 一般用法

5.2 采样聚合

5.3 采样组的迭代

6. 窗口函数

6.1 Rolling

6.1.1 常用聚合

6.1.2 rolling的apply聚合

6.1.3 基于时间的rolling

6.2 Expanding

6.2.1 expanding函数

6.2.2 几个特别的Expanding类型函数

1. 学习内容

1. 学会时序类型数据的创建

2. 了解时序数据的索引与属性

3. 对时序数据进行重采样

本项目参见https://github.com/datawhalechina/team-learning/tree/master/Pandas%E6%95%99%E7%A8%8B%EF%BC%88%E4%B8%8A%EF%BC%89

2. 准备工作

import pandas as pd
import numpy as np

3. 创建时序数据

3.1 时序数据类型

图3.1 时序数据类型

3.2 创建时间点

3.2.1 to_datetime()方法

pandas在时间点建立的输入格式规定上给了很大的自由度,很多表示时间的字符串都能直接且正确建立同一时间点。而对于无法直接建立的数据,也可以使用format参数来指定字符串格式从而建立时间点。

pd.to_datetime('2020\\1\\1', format = '%Y\\%m\\%d')
pd.to_datetime('2020`1`1', format = '%Y`%m`%d')
pd.to_datetime('2020.1 1', format = '%Y.%m %d')
pd.to_datetime('1 1.2020', format = '%d %m.%Y')
Timestamp('2020-01-01 00:00:00')

同时,使用列表可以将其转为时间点索引。

pd.Series(range(2), index = pd.to_datetime(['2020/1/1', '2020/1/2']))
2020-01-01    0
2020-01-02    1
dtype: int64

对于DataFrame而言,如果列已经按照时间顺序排好,则利用to_datetime可自动转换。

df = pd.DataFrame({'year': [2020, 2020], 'month': [1, 1], 'day': [1, 2]})
pd.to_datetime(df)
0   2020-01-01
1   2020-01-02
dtype: datetime64[ns]

事实上,Timestamp的精度远远不止day,可以最小到纳秒ns。当然,缩小精度的代价是缩小表示范围。

pd.to_datetime('2020/1/1 00:00:00.123456789')
Timestamp('2020-01-01 00:00:00.123456789')
print(pd.Timestamp.min)
print(pd.Timestamp.max)
1677-09-21 00:12:43.145225
2262-04-11 23:47:16.854775807

3.2.2 date_range()方法

一般来说,start/end/periods(时间点个数)/freq(间隔方法)是该方法最重要的参数,给定了其中的3个,剩下的一个就会被确定。

pd.date_range(start = '2020/1/1', end = '2020/1/10', periods = 3)
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-05 12:00:00',
               '2020-01-10 00:00:00'],
              dtype='datetime64[ns]', freq=None)

其中freq参数有许多选项,下面将常用部分罗列如下:

图3.2 freq参数的部分选项

3.2.3 bdate_range()方法

bdate_range是一个类似与date_range的方法,特点在于可以在自带的工作日间隔设置上,再选择weekmask参数和holidays参数。它的freq中有一个特殊的'C'/'CBM'/'CBMS'选项,表示定制,需要联合weekmask参数和holidays参数使用。

# 例如现在需要将工作日中的周一、周二、周五3天保留,并将部分holidays剔除
weekmask = 'Mon Tue Fri'
holidays = [pd.Timestamp('2020/1/%s' %i) for i in range(7, 13)]
#注意holidays
pd.bdate_range(start = '2020-1-1',end = '2020-1-15', freq = 'C', \
               weekmask = weekmask, holidays = holidays)
DatetimeIndex(['2020-01-03', '2020-01-06', '2020-01-13', '2020-01-14'], dtype='datetime64[ns]', freq='C')

3.3 DateOffset对象

3.3.1 DateOffset与Timedelta的区别

Timedelta绝对时间差的特点指无论是冬令时还是夏令时,增减1day都只计算24小时。DateOffset相对时间差指,无论一天是23\24\25小时,增减1day都与当天相同的时间保持一致。例如,英国当地时间 2020年03月29日,01:00:00 时钟向前调整 1 小时 变为 2020年03月29日,02:00:00,开始夏令时。

4. 时序的索引及属性

4.1 索引切片

rng = pd.date_range('2020', '2021', freq = 'W')
ts = pd.Series(np.random.randn(len(rng)), index = rng)
ts.head()
2020-01-05   -0.355636
2020-01-12    2.377644
2020-01-19   -0.918134
2020-01-26   -0.136201
2020-02-02   -1.320732
Freq: W-SUN, dtype: float64
# 合法字符自动转换为时间点
ts['2020-01-26': '20200726'].head()
2020-01-26   -0.136201
2020-02-02   -1.320732
2020-02-09   -0.180517
2020-02-16   -0.346887
2020-02-23    0.663864
Freq: W-SUN, dtype: float64

4.2 子集索引

ts['2020-7'].head()
2020-07-05    0.911370
2020-07-12   -0.949458
2020-07-19    0.754932
2020-07-26    0.014313
Freq: W-SUN, dtype: float64
# 支持混合形态索引
ts['2011-1': '20200726'].head()
2020-01-05   -0.355636
2020-01-12    2.377644
2020-01-19   -0.918134
2020-01-26   -0.136201
2020-02-02   -1.320732
Freq: W-SUN, dtype: float64

4.3 时间点的属性

采用dt对象可以轻松获得关于时间的信息。

pd.Series(ts.index).dt.week.head()
0    1
1    2
2    3
3    4
4    5
dtype: int64
pd.Series(ts.index).dt.day.head()
0     5
1    12
2    19
3    26
4     2
dtype: int64

利用strftime可重新修改时间格式。

pd.Series(ts.index).dt.strftime('%Y-间隔1-%m-间隔2-%d').head()
0    2020-01-05 00:00:00
1    2020-01-12 00:00:00
2    2020-01-19 00:00:00
3    2020-01-26 00:00:00
4    2020-02-02 00:00:00
dtype: object

对于datetime对象可以直接通过属性获取信息。

pd.date_range('2020', '2021', freq = 'W').month
Int64Index([ 1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  3,  3,  4,  4,  4,  4,
             5,  5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
             8,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12,
            12],
           dtype='int64')
pd.date_range('2020', '2021', freq = 'W').weekday
Int64Index([6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
            6, 6, 6, 6, 6, 6, 6, 6],
           dtype='int64')

5. 重采样

所谓重采样,就是指resample函数,它可以看做时序版本的groupby函数。

5.1 一般用法

采样频率一般设置为上面提到的offset字符。

df_r = pd.DataFrame(np.random.randn(1000, 3), \
                    index = pd.date_range('1/1/2020', freq = 'S', periods = 1000), \
                    columns = ['A', 'B', 'C'])
r = df_r.resample('3min')
r.sum()
                             A          B          C
2020-01-01 00:00:00   2.357245 -16.806970   7.988968
2020-01-01 00:03:00 -10.272145  15.806088 -25.279588
2020-01-01 00:06:00   2.544400  12.645482  -3.338972
2020-01-01 00:09:00  -0.872054  12.439237  15.888432
2020-01-01 00:12:00  -1.293978  16.658237  16.703369
2020-01-01 00:15:00   9.466841  -5.728703   2.354720
df_r2 = pd.DataFrame(np.random.randn(200, 3), \
                     index = pd.date_range('1/1/2020', freq = 'D', periods = 200), \
                     columns = ['A', 'B', 'C'])
r = df_r2.resample('CBMS')
r.sum()
                   A         B          C
2020-01-01 -0.990115 -0.460111  -3.429150
2020-02-03  7.131371  0.498715   2.033721
2020-03-02  4.153905 -3.487473  10.328431
2020-04-01 -0.583855 -3.208713  -6.282215
2020-05-01  2.083735  1.235905   1.326104
2020-06-01  2.496877 -0.014361  -3.089092
2020-07-01 -3.104211  7.385895  -1.652805

5.2 采样聚合

r = df_r.resample('3T')
r['A'].mean()
2020-01-01 00:00:00   -0.035590
2020-01-01 00:03:00   -0.134152
2020-01-01 00:06:00   -0.009651
2020-01-01 00:09:00    0.037712
2020-01-01 00:12:00    0.024681
2020-01-01 00:15:00    0.018664
Freq: 3T, Name: A, dtype: float64

5.3 采样组的迭代

采样组的迭代和groupby迭代完全类似,对于每一个组都可以分别做相应操作。

date_list = ['2020-01-01 00:00:00', '2020-01-01 00:30:00', \
             '2020-01-01 00:31:00', '2020-01-01 01:00:00', \
             '2020-01-01 03:00:00', '2020-01-01 03:05:00']
small = pd.Series(range(6),index = pd.to_datetime(date_list))
resampled = small.resample('H')
for name, group in resampled:
    print("Group: ", name)
    print("-" * 27)
    print(group, end = "\n\n")
Group:  2020-01-01 00:00:00
---------------------------
2020-01-01 00:00:00    0
2020-01-01 00:30:00    1
2020-01-01 00:31:00    2
dtype: int64

Group:  2020-01-01 01:00:00
---------------------------
2020-01-01 01:00:00    3
dtype: int64

Group:  2020-01-01 02:00:00
---------------------------
Series([], dtype: int64)

Group:  2020-01-01 03:00:00
---------------------------
2020-01-01 03:00:00    4
2020-01-01 03:05:00    5
dtype: int64

6. 窗口函数

下面主要介绍pandas中两类主要的窗口(window)函数:rolling/expanding。

s = pd.Series(np.random.randn(1000), \
              index = pd.date_range('1/1/2020', periods = 1000))
s.head()
2020-01-01   -0.346470
2020-01-02   -1.372667
2020-01-03   -0.026028
2020-01-04    0.696390
2020-01-05    0.684197
Freq: D, dtype: float64

6.1 Rolling

6.1.1 常用聚合

所谓rolling方法,就是规定一个窗口,它和groupby对象一样,本身不会进行操作,需要配合聚合函数才能计算结果。

s.rolling(window = 50)
Rolling [window=50,center=False,axis=0]
s.rolling(window = 50).mean()
2020-01-01         NaN
2020-01-02         NaN
2020-01-03         NaN
2020-01-04         NaN
2020-01-05         NaN
                ...   
2022-09-22   -0.131049
2022-09-23   -0.121698
2022-09-24   -0.111032
2022-09-25   -0.096440
2022-09-26   -0.113077
Freq: D, Length: 1000, dtype: float64

min_periods参数是指需要的非缺失数据点数量阀值。

s.rolling(window = 50, min_periods = 3).mean().head()
2020-01-01         NaN
2020-01-02         NaN
2020-01-03   -0.581722
2020-01-04   -0.262194
2020-01-05   -0.072916
Freq: D, dtype: float64

6.1.2 rolling的apply聚合

使用apply聚合时,只需记住传入的是window大小的Series,输出的必须是标量即可,比如如下计算变异系数。

s.rolling(window = 50, min_periods = 3).apply(lambda x: x.std() / x.mean()).head()
2020-01-01          NaN
2020-01-02          NaN
2020-01-03    -1.209285
2020-01-04    -3.277140
2020-01-05   -11.740584
Freq: D, dtype: float64

6.1.3 基于时间的rolling

s.rolling('15D').mean().head()
2020-01-01   -0.346470
2020-01-02   -0.859568
2020-01-03   -0.581722
2020-01-04   -0.262194
2020-01-05   -0.072916
Freq: D, dtype: float64

可选closed='right'(默认)'left''both''neither'参数,决定端点的包含情况。

s.rolling('15D', closed = 'right').sum().head()
2020-01-01   -0.346470
2020-01-02   -1.719137
2020-01-03   -1.745165
2020-01-04   -1.048775
2020-01-05   -0.364578
Freq: D, dtype: float64

6.2 Expanding

6.2.1 expanding函数

普通的expanding函数等价与rolling(window=len(s),min_periods=1),是对序列的累计计算。

s.rolling(window = len(s), min_periods = 1).sum().head()
2020-01-01   -0.346470
2020-01-02   -1.719137
2020-01-03   -1.745165
2020-01-04   -1.048775
2020-01-05   -0.364578
Freq: D, dtype: float64
s.expanding().sum().head()
2020-01-01   -0.346470
2020-01-02   -1.719137
2020-01-03   -1.745165
2020-01-04   -1.048775
2020-01-05   -0.364578
Freq: D, dtype: float64
s.expanding().apply(lambda x: sum(x)).head()
2020-01-01   -0.346470
2020-01-02   -1.719137
2020-01-03   -1.745165
2020-01-04   -1.048775
2020-01-05   -0.364578
Freq: D, dtype: float64

6.2.2 几个特别的Expanding类型函数

cumsum/cumprod/cummax/cummin都是特殊expanding累计计算方法。

s.cumsum().head()
2020-01-01   -0.346470
2020-01-02   -1.719137
2020-01-03   -1.745165
2020-01-04   -1.048775
2020-01-05   -0.364578
Freq: D, dtype: float64

shift/diff/pct_change都是涉及到了元素关系:

shift是指序列索引不变,但值向后移动;

diff是指前后元素的差,period参数表示间隔,默认为1,并且可以为负;

pct_change是值前后元素的变化百分比,period参数与diff类似。

s.shift(2).head()
2020-01-01         NaN
2020-01-02         NaN
2020-01-03   -0.346470
2020-01-04   -1.372667
2020-01-05   -0.026028
Freq: D, dtype: float64
s.diff(3).head()
2020-01-01         NaN
2020-01-02         NaN
2020-01-03         NaN
2020-01-04    1.042860
2020-01-05    2.056864
Freq: D, dtype: float64
s.pct_change(3).head()
2020-01-01         NaN
2020-01-02         NaN
2020-01-03         NaN
2020-01-04   -3.009957
2020-01-05   -1.498444
Freq: D, dtype: float64

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值