为什么要学习时间序列

在许多数据分析中都会遇见与时间有关的数据,他们可能是字符串…各种各样的格式,Pandas有良好的工具可以帮助我们处理这些数据,它的优势体现在处理时间和处理难度。

date_range方法

pd.date_range(start=None, end=None, periods=None, freq=’D’)
开始时间 结束时间 周期 频率
start和end以及freq配合能够生成start和end范围内以频率freq的一组时间索引(D是一天,可以写nD表示n天,M表示月)
但下面这种用的更多
start和periods(周期=n,每隔n个取一个)以及freq配合能够生成从start开始的频率为freq的periods个时间索引
start可以写的格式很多 20190101,2019-01-01,2019/01/01,2019.01.01
image.png

  1. import pandas as pd
  2. import numpy as np
  3. date_list = pd.date_range(start='20190101',end='20190202',freq='D')
  4. print(date_list)
  5. ------------output------------
  6. DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
  7. '2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
  8. '2019-01-09', '2019-01-10', '2019-01-11', '2019-01-12',
  9. '2019-01-13', '2019-01-14', '2019-01-15', '2019-01-16',
  10. '2019-01-17', '2019-01-18', '2019-01-19', '2019-01-20',
  11. '2019-01-21', '2019-01-22', '2019-01-23', '2019-01-24',
  12. '2019-01-25', '2019-01-26', '2019-01-27', '2019-01-28',
  13. '2019-01-29', '2019-01-30', '2019-01-31', '2019-02-01',
  14. '2019-02-02'],
  15. dtype='datetime64[ns]', freq='D')

案例

美国蒙哥马利 2015到2017年25万条911的紧急电话的数据
montcoalert.zip
数据来自:https://www.kaggle.com/mchirico/montcoalert/data

预览

image.png

如果不用这些知识,想要获得每天报警人数

  1. import numpy as np
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. all_datas = pd.read_csv('/home/kesci/work/mydata/911.csv')
  5. all_datas["timeStamp"] = all_datas["timeStamp"].str.split(' ').tolist()
  6. print(all_datas["timeStamp"].shape[0])
  7. a = np.ones((all_datas["timeStamp"].shape[0],)).astype('int')
  8. one_data = pd.Series(a).to_frame()
  9. one_data.columns = ['count']
  10. time_data = all_datas["timeStamp"]
  11. last_data = one_data.join(time_data)
  12. last_data["timeStamp"] = last_data.timeStamp.apply(lambda x: x[0] if True else np.nan)
  13. # print(last_data.groupby(by='timeStamp').count())
  14. draw_data = last_data.groupby(by='timeStamp').count()
  15. _x = range(draw_data["count"].shape[0])
  16. _y = list(draw_data.values)
  17. print(draw_data.shape[0])
  18. plt.figure(figsize=(20,8),dpi=80)
  19. plt.plot(_x, _y) # 绘制点
  20. plt.xticks(range(0,draw_data.shape[0],50),list(draw_data.index.tolist())[::50],rotation=45) # 设置x坐标轴
  21. plt.yticks(range(0, int(max(_y))+1,150)) # 设置y坐标轴
  22. plt.show()

image.png

将时间作为索引

  1. >>> time = pd.date_range(start='20190101',periods=10,freq='D')
  2. >>> df = pd.DataFrame(np.random.rand(10),index=time)
  3. >>> df
  4. 0
  5. 2019-01-01 0.927232
  6. 2019-01-02 0.888231
  7. 2019-01-03 0.611534
  8. 2019-01-04 0.889452
  9. 2019-01-05 0.849799
  10. 2019-01-06 0.317802
  11. 2019-01-07 0.189140
  12. 2019-01-08 0.910831
  13. 2019-01-09 0.621555
  14. 2019-01-10 0.616275

转化为时间序列

回到最开始的911数据的案例中,我们可以使用pandas提供的方法把时间字符串转化为时间序列
df[“timeStamp”] = pd.to_datetime(df[“timeStamp”],format=””)
format参数大部分情况下可以不用写,但是对于pandas无法格式化的时间字符串,我们可以使用该参数,比如包含中文
格式传参
http://www.runoob.com/python3/python3-date-time.html
image.png

重采样

如果我们想要看到以天为单位的数据,那么我们就要进行重采样
重采样:指的是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率数据转化为低频率数据为降采样,低频率转化为高频率为升采样。
pandas提供了一个resample的方法来帮助我们实现频率转化

.resample

还是刚刚的数据

  1. import numpy as np
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. all_datas = pd.read_csv('/home/kesci/input/study_data3465/911.csv')
  5. a = np.ones((all_datas["timeStamp"].shape[0],)).astype('int')
  6. just_one = pd.Series(a).to_frame()
  7. using_data = pd.to_datetime(all_datas["timeStamp"])
  8. using_data = using_data.to_frame().join(just_one)
  9. using_data.set_index("timeStamp",inplace=True)
  10. using_data = using_data.resample('M').count()
  11. using_data.columns = ['sum']
  12. print(using_data.head(5))
  13. _x = range(using_data.shape[0])
  14. _y = list(using_data['sum'])
  15. plt.figure(figsize=(20,8),dpi=80)
  16. plt.plot(_x, _y) # 绘制点
  17. plt.xticks(range(0,using_data.shape[0],2),list(map(lambda x:str(x)[:10],using_data.index))[::2],rotation=45) # 设置x坐标轴
  18. plt.yticks(range(5000, int(max(_y))+1,1000)) # 设置y坐标轴
  19. plt.show()

image.png

官网的栗子

  1. >>> d = dict({'price': [10, 11, 9, 13, 14, 18, 17, 19],
  2. ... 'volume': [50, 60, 40, 100, 50, 100, 40, 50]})
  3. >>> df = pd.DataFrame(d)
  4. >>> df['week_starting'] = pd.date_range('01/01/2018',
  5. ... periods=8,
  6. ... freq='W')
  7. >>> df
  8. price volume week_starting
  9. 0 10 50 2018-01-07
  10. 1 11 60 2018-01-14
  11. 2 9 40 2018-01-21
  12. 3 13 100 2018-01-28
  13. 4 14 50 2018-02-04
  14. 5 18 100 2018-02-11
  15. 6 17 40 2018-02-18
  16. 7 19 50 2018-02-25
  17. >>> df.resample('M', on='week_starting').mean()
  18. price volume
  19. week_starting
  20. 2018-01-31 10.75 62.5
  21. 2018-02-28 17.00 60.0

For a DataFrame with MultiIndex, the keyword level can be used to specify on which level the resampling needs to take place.

  1. >>> days = pd.date_range('1/1/2000', periods=4, freq='D')
  2. >>> d2 = dict({'price': [10, 11, 9, 13, 14, 18, 17, 19],
  3. ... 'volume': [50, 60, 40, 100, 50, 100, 40, 50]})
  4. >>> df2 = pd.DataFrame(d2,
  5. ... index=pd.MultiIndex.from_product([days,
  6. ... ['morning',
  7. ... 'afternoon']]
  8. ... ))
  9. >>> df2
  10. price volume
  11. 2000-01-01 morning 10 50
  12. afternoon 11 60
  13. 2000-01-02 morning 9 40
  14. afternoon 13 100
  15. 2000-01-03 morning 14 50
  16. afternoon 18 100
  17. 2000-01-04 morning 17 40
  18. afternoon 19 50
  19. >>> df2.resample('D', level=0).sum()
  20. price volume
  21. 2000-01-01 21 110
  22. 2000-01-02 22 140
  23. 2000-01-03 32 150
  24. 2000-01-04 36 90

增加与时间有关的特征

DatetimeIndex
image.png
这里面的都可以取
image.png