飞道的博客

pandas数据分析基础之时间序列

291人阅读  评论(0)

一、时间序列是什么

时间序列在多个时间点观察或测量到的任何事物,很多都是固定频率出现 的,比如每15秒、每5分钟、每月。
padnas提供了一组标准的时间序列处理工具和数据算法,基本的时间序列类型是以时间戳为索引的Series。
当创建一个带有DatetimeIndex的Series时,pandas就会知道对象是一个时间序列,用Numpy的datetime64数据以纳秒形式存储时间。


  
  1. dates=[
  2. datetime( 2020, 1, 2),datetime( 2020, 1, 5),datetime( 2020, 1, 7),
  3. datetime( 2020, 1, 8),datetime( 2020, 1, 10),datetime( 2020, 1, 12)
  4. ]
  5. ts=pd.Series(np.random.randn( 6), index=dates)
  6. ts
  7. 2020- 01- 02 - 0.140776
  8. 2020- 01- 05 0.185088
  9. 2020- 01- 07 0.555777
  10. 2020- 01- 08 0.693348
  11. 2020- 01- 10 - 0.213715
  12. 2020- 01- 12 - 0.259721
  13. dtype: float64
  14. ts. index
  15. DatetimeIndex([ '2020-01-02', '2020-01-05', '2020-01-07', '2020-01-08',
  16. '2020-01-10', '2020-01-12'],
  17. dtype= 'datetime64[ns]', freq=None)
  18. ts. index.dtype
  19. dtype( '<M8[ns]')

二、时间序列的选取-时间字符串/at_time/between_time/asof

1.传入一个可以被解释为日期的字符串


  
  1. ts ['1/10/2020']
  2. -0 .3216128833894315
  3. ts ['2020-01-02']
  4. 0 .47508960825683716
  5. #也可以只传入年或月
  6. longer_ts ['2021']
  7. 2021 -01-01 1 .596179
  8. 2021 -01-02 -0 .458160
  9. 2021 -01-03 1 .380482
  10. ...
  11. 2021 -12-29 0 .343524
  12. 2021 -12-30 0 .040584
  13. 2021 -12-31 -1 .616620
  14. Freq: D, Length: 365, dtype: float64
  15. #通过日期进行切片
  16. ts [datetime(2020,1,7):]
  17. 2020 -01-07 0 .555777
  18. 2020 -01-08 0 .693348
  19. 2020 -01-10 -0 .213715
  20. 2020 -01-12 -0 .259721
  21. dtype: float64
  22. ts ['1/6/2020':'1/11/2020']
  23. 2020 -01-07 0 .555777
  24. 2020 -01-08 0 .693348
  25. 2020 -01-10 -0 .213715
  26. dtype: float64

2.通过at_time获取指定时间点


  
  1. # 生成一个交易日内的日期范围和时间序列,以分为纬度
  2. rng=pd.date_range( '2020-06-01 09:30', '2020-06-01 15:59',freq= 'T')
  3. #生成5天的时间点
  4. rng=rng.append([rng+pd.offsets.BDay(i) for i in range(1,4)])
  5. ts=pd.Series(np.arange(len(rng),dtype= float),index=rng)

  
  1. #抽取指定时间点:10点0分的数据
  2. ts.at_time( time( 10, 0))

3.通过between_time获取两个时间点之间的数据

ts.between_time(time(10,0),time(10,1))

4.通过asof获取最接近当前时间的数据
asof解释:最后一行不是NaN值的值。通俗的说:假如我有一组数据,某个点的时候这个值是NaN,那就求这个值之前最近一个不是NaN的值是多少


  
  1. selection=pd.date_range( '2020-06-01 10:00',periods= 4,freq= 'B')
  2. ts.asof(selection)

三、时间序列的生成-datetime/date_range(start,end,perios,freq)

1.直接使用date_time生成


  
  1. dates=[
  2. datetime( 2020, 1, 2),datetime( 2020, 1, 5),datetime( 2020, 1, 7),
  3. datetime( 2020, 1, 8),datetime( 2020, 1, 10),datetime( 2020, 1, 12)
  4. ]
  5. ts=pd.Series(np.random.randn( 6), index=dates)

date_range可以生成指定长度的DatetimeIndex

  • 指定开始和结束

  
  1. pd.date_range( '4/1/2020', '6/1/2020')
  2. DatetimeIndex([ '2020-04-01', '2020-04-02', '2020-04-03', '2020-04-04',
  3. '2020-04-05', '2020-04-06', '2020-04-07', '2020-04-08',
  4. '2020-04-09', '2020-04-10', '2020-04-11', '2020-04-12',
  5. '2020-04-13', '2020-04-14', '2020-04-15', '2020-04-16',
  6. '2020-04-17', '2020-04-18', '2020-04-19', '2020-04-20',
  7. '2020-04-21', '2020-04-22', '2020-04-23', '2020-04-24',
  8. '2020-04-25', '2020-04-26', '2020-04-27', '2020-04-28',
  9. '2020-04-29', '2020-04-30', '2020-05-01', '2020-05-02',
  10. '2020-05-03', '2020-05-04', '2020-05-05', '2020-05-06',
  11. '2020-05-07', '2020-05-08', '2020-05-09', '2020-05-10',
  12. '2020-05-11', '2020-05-12', '2020-05-13', '2020-05-14',
  13. '2020-05-15', '2020-05-16', '2020-05-17', '2020-05-18',
  14. '2020-05-19', '2020-05-20', '2020-05-21', '2020-05-22',
  15. '2020-05-23', '2020-05-24', '2020-05-25', '2020-05-26',
  16. '2020-05-27', '2020-05-28', '2020-05-29', '2020-05-30',
  17. '2020-05-31', '2020-06-01'],
  18. dtype= 'datetime64[ns]', freq= 'D')
  • 指定步长

  
  1. pd.date_range( start= '4/1/2020',periods= 20)
  2. DatetimeIndex([ '2020-04-01', '2020-04-02', '2020-04-03', '2020-04-04',
  3. '2020-04-05', '2020-04-06', '2020-04-07', '2020-04-08',
  4. '2020-04-09', '2020-04-10', '2020-04-11', '2020-04-12',
  5. '2020-04-13', '2020-04-14', '2020-04-15', '2020-04-16',
  6. '2020-04-17', '2020-04-18', '2020-04-19', '2020-04-20'],
  7. dtype= 'datetime64[ns]', freq= 'D')
  • 指定偏移量

M:日历月末最后一天


  
  1. pd.date_range( '1/1/2020', '12/1/2020',freq= 'M')
  2. DatetimeIndex([ '2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
  3. '2020-05-31', '2020-06-30', '2020-07-31', '2020-08-31',
  4. '2020-09-30', '2020-10-31', '2020-11-30'],
  5. dtype= 'datetime64[ns]', freq= 'M')

BM:每月的最后个工作日,business end of month


  
  1. pd.date_range( '1/1/2020', '12/1/2020',freq= 'BM')
  2. DatetimeIndex([ '2020-01-31', '2020-02-28', '2020-03-31', '2020-04-30',
  3. '2020-05-29', '2020-06-30', '2020-07-31', '2020-08-31',
  4. '2020-09-30', '2020-10-30', '2020-11-30'],
  5. dtype= 'datetime64[ns]', freq= 'BM')

自定义时间偏移,如h、4h、1h30min


  
  1. pd.date_range( '1/1/2020',periods= 10,freq= '1h30min')
  2. DatetimeIndex([ '2020-01-01 00:00:00', '2020-01-01 01:30:00',
  3. '2020-01-01 03:00:00', '2020-01-01 04:30:00',
  4. '2020-01-01 06:00:00', '2020-01-01 07:30:00',
  5. '2020-01-01 09:00:00', '2020-01-01 10:30:00',
  6. '2020-01-01 12:00:00', '2020-01-01 13:30:00'],
  7. dtype= 'datetime64[ns]', freq= '90T')

四、时间序列的偏移量对照表-freq

名称 偏移量类型 说明
D Day 每日
B BusinessDay 每工作日
H Hour 每小时
T或min Minute 每分
S Second 每秒
L或ms Milli 每毫秒
U Micro 每微秒
M MounthEnd 每月最后一个日历日
BM BusinessMonthEnd 每月最后一个工作日
MS MonthBegin 每月每一个工作日
BMS BusinessMonthBegin 每月第一个工作日
W-MON、W-TUE... Week 指定星期几(MON、TUE、WED、THU、FRI、SAT、SUM)
WOM-1MON、WMON-2MON WeekOfMonth 产生每月第一、第二、第三或第四周的星期几
Q-JAN、Q-FEB... QuaterEnd 对于以指定月份(JAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV、DEC)结束的年度,每季度最后一月的最后一个日历日
BQ-JAN、BQ-FEB... BusinessQuaterEnd 对于以指定月份结束的年度,每季度最后一月的最后一个工作日
QS-JAN、QS-FEB... QuaterBegin 对于以指定月份结束的年度,每季度最后一月的第一个日历日
QS-JAN、QS-FEB... BusinessQuaterBegin 对于指定月份结束的年度,每季度最后一月的第一个工作日
A-JAN、A-FEB... YearEnd 每年指定月份的最后一个日历日
BA-JAN、BA-FEB BusinessYearEnd 每年指定月份的最后一个日历日
AS-JAN、AS-FEB YearBegin 每年指定月份的第一个日历日
BAS-JAN、BAS-FEB BusinessYearBegin 每年指定月份的第一个工作日

例如,每月第3个星期五


  
  1. pd.date_range( '1/1/2020', '9/1/2020',freq= 'WOM-3FRI')
  2. DatetimeIndex([ '2020-01-17', '2020-02-21', '2020-03-20', '2020-04-17',
  3. '2020-05-15', '2020-06-19', '2020-07-17', '2020-08-21'],
  4. dtype= 'datetime64[ns]', freq= 'WOM-3FRI')

五、时间序列的前移或后移-shift/通过Day或MonthEnd

shift方法用于执行单纯的前移或后移操作


  
  1. ts=pd.Series(np.random.randn( 4),
  2. index=pd.date_range( '1/1/2020',periods= 4,freq= 'M'))
  3. ts
  4. 2020 -01 -31 0.185458
  5. 2020 -02 -29 0.549704
  6. 2020 -03 -31 0.146584
  7. 2020 -04 -30 0.983613
  8. Freq: M, dtype: float64

向后移动一个月


  
  1. ts.shift( 1,freq= 'M')
  2. 2020 -02 -29 0.185458
  3. 2020 -03 -31 0.549704
  4. 2020 -04 -30 0.146584
  5. 2020 -05 -31 0.983613
  6. Freq: M, dtype: float64

向前移动3天


  
  1. ts.shift( -3,freq= 'D')
  2. 2020 -01 -28 0.185458
  3. 2020 -02 -26 0.549704
  4. 2020 -03 -28 0.146584
  5. 2020 -04 -27 0.983613
  6. dtype: float64

通过Day或MonthEnd移动


  
  1. from pandas.tseries.offsets import Day,MonthEnd
  2. now=datetime( 2020, 1, 27)
  3. now+ 3* Day()
  4. Timestamp( '2020-01-30 00:00:00')
  5. now+MonthEnd()
  6. Timestamp( '2020-01-31 00:00:00')

五、时区处理-tz/tz_convert

python的时区信息来自第三方库pytz,pandas包装了pytz的功能
查看所有时区

pytz.common_timezones

转换时区- tz_convert


  
  1. rng=pd.date_range( '3/9/2020 9:30',periods= 6,freq= 'D',tz= 'UTC')
  2. ts=pd.Series(np.random.randn( len(rng)),index=rng)
  3. ts
  4. 2020 -03 -09 09: 30: 00+ 00: 00 -1.779006
  5. 2020 -03 -10 09: 30: 00+ 00: 00 -0.293860
  6. 2020 -03 -11 09: 30: 00+ 00: 00 -0.174114
  7. 2020 -03 -12 09: 30: 00+ 00: 00 0.749316
  8. 2020 -03 -13 09: 30: 00+ 00: 00 0.342134
  9. 2020 -03 -14 09: 30: 00+ 00: 00 1.101283
  10. Freq: D, dtype: float64
  11. ts.tz_convert( 'Asia/Shanghai')
  12. 2020 -03 -09 17: 30: 00+ 08: 00 -1.779006
  13. 2020 -03 -10 17: 30: 00+ 08: 00 -0.293860
  14. 2020 -03 -11 17: 30: 00+ 08: 00 -0.174114
  15. 2020 -03 -12 17: 30: 00+ 08: 00 0.749316
  16. 2020 -03 -13 17: 30: 00+ 08: 00 0.342134
  17. 2020 -03 -14 17: 30: 00+ 08: 00 1.101283
  18. Freq: D, dtype: float64

六、时期及算术运算-period

时期(period)表示的是时间区间,比如数日、数月、数季、数年等
下面这个Period对象表示从2020年1月1日到2020年12月31日之间的整段时间


  
  1. p=pd.Period( 2020,freq= 'A-DEC')
  2. p
  3. Period ('2020', 'A-DEC')

创建规则的时期范围


  
  1. #季度为Q生成13个时间
  2. pd.period_range( "2019-01", periods= 13, freq= "Q")
  3. #Q代表季度为频率,默认的后缀为DEC代表一年以第1个月为结束【最后一个月为1月份】
  4. pd.period_range( "2019-01", periods= 13, freq= "Q-JAN")
  5. # 以季度Q【年为频率】生成13个时间
  6. pd.period_range( "2019-01", periods= 13, freq= "Y")
  7. #以季度Q【2个月为频率】生成13个时间
  8. pd.period_range( "2019-01", periods= 13, freq= "2m")

PeriodIndex类保存了一组Period,可以在pandas数据结构中用作轴索引


  
  1. rng=pd.period_range( '1/1/2020', '6/30/2020',freq= 'M')
  2. rng
  3. PeriodIndex([ '2020-01', '2020-02', '2020-03', '2020-04', '2020-05', '2020-06'], dtype= 'period[M]', freq= 'M')
  4. pd.Series(np.random.randn( 6),rng)
  5. 2020 -01 -1.050150
  6. 2020 -02 -0.828435
  7. 2020 -03 1.648335
  8. 2020 -04 1.476485
  9. 2020 -05 0.779732
  10. 2020 -06 -1.394688
  11. Freq: M, dtype: float64

使用字符串创建PeriodIndex
Q代表季度为频率,默认的后缀为DEC代表一年以第12个月为结束

pd.PeriodIndex(['2020Q3','2020Q2','2020Q1'],freq='Q-DEC')

Period和PeriodIndex互转-asfreq


  
  1. p=pd.Period( '2020',freq= 'A-DEC')
  2. p.asfre q('M',how='start')
  3. Period( '2020-01', 'M')
  4. p=pd.Period( '2020-08',freq= 'M')
  5. p.asfre q('A-JUN')
  6. Period( '2021', 'A-JUN')

to_period可以将datetime转period


  
  1. rng=pd.date_range( '1/1/2020',periods= 6,freq= 'D')
  2. ts=pd.Series(np.random.randn( 6),index=rng)
  3. ts
  4. 2020 -01 -01 -1.536552
  5. 2020 -01 -02 -0.550879
  6. 2020 -01 -03 0.601546
  7. 2020 -01 -04 -0.103521
  8. 2020 -01 -05 0.445024
  9. 2020 -01 -06 1.127598
  10. Freq: D, dtype: float64
  11. ts.to_period( 'M')
  12. 2020 -01 -1.536552
  13. 2020 -01 -0.550879
  14. 2020 -01 0.601546
  15. 2020 -01 -0.103521
  16. 2020 -01 0.445024
  17. 2020 -01 1.127598
  18. Freq: M, dtype: float64

to_timespame可以将Period转换为时间戳

ts.to_period('M').to_timestamp()

七、频率转换-resample

重采样(resampling)指将时间序列从一个频率转换到另一个频率的处理过程
pandas对象都带有一个resample方法,是各种频率转换的函数

降采样率


  
  1. #查看100天的采样
  2. rng=pd.date_range( '1/1/2020',periods= 100,freq= 'D')
  3. ts=pd.Series(np.random.randn(len(rng)), index=rng)
  4. # 转为一月的
  5. ts.resample( 'M').mean()
  6. 2020- 01- 31 - 0. 049213
  7. 2020- 02- 29 - 0. 155195
  8. 2020- 03- 31 - 0. 000091
  9. 2020- 04- 30 - 0. 023561
  10. Freq: M, dtype: float64

分钟的采样转为5分钟的


  
  1. rng=pd.date_range( '1/1/2020',periods= 12,freq= 'T')
  2. ts=pd.Series(np.random.randn( len(rng)),index=rng)
  3. ts.resample( '5min').sum()
  4. 2020 -01 -01 00: 00: 00 1.376219
  5. 2020 -01 -01 00: 05: 00 0.883248
  6. 2020 -01 -01 00: 10: 00 -0.939534
  7. Freq: 5T, dtype: float64

通过groupby进行采样,传入一个能够访问时间序列的索引上字段的函数


  
  1. rng=pd.date_range( '1/1/2020',periods= 100,freq= 'D')
  2. ts=pd.Series(np.random.randn( len(rng)),index=rng)
  3. ts.groupby(lambda x:x.month).mean()
  4. 2020 -01 -31 0.182420
  5. 2020 -02 -29 0.200134
  6. 2020 -03 -31 -0.108818
  7. 2020 -04 -30 -0.187426
  8. Freq: M, dtype: float64

升采样率
示例: 周数据转为日


  
  1. # 周数据
  2. frame=pd.DataFrame(
  3. np.random.randn( 2, 4),
  4. index=pd.date_range( '1/1/2020',periods= 2,freq= 'W-WED'),
  5. columns=[ 'Colorado', 'Texa', 'New York', 'Ohio']
  6. )
  7. # #转为日
  8. frame.resample( 'D').asfre q()
  9. #用前面的值填充
  10. frame.resample( 'D').ffill()
  11. #用后面的值填充
  12. frame.resample( 'D').bfill()

转载:https://blog.csdn.net/songfei_dream/article/details/104107884
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场