内容目录

  • 1. 基础概述
  • 2. 转换时间戳
  • 3. 生成时间戳范围
  • 4. DatetimeIndex
  • 5. DateOffset对象
  • 6. 与时间序列相关的方法
  • 6.1 移动
  • 6.2 频率转换
  • 6.3 重采样

 在处理时间序列的的过程中,我们经常会去做以下一些任务:

  1. 生成固定频率日期和时间跨度的序列
  2. 将时间序列整合或转换为特定频率
  3. 基于各种非标准时间增量(例如,在一年的最后一个工作日之前的5个工作日)计算“相对”日期,或向前或向后“滚动”日期

使用 Pandas 可以轻松完成以上任务。

一、基础概述

  1. 下面列出了 Pandas 和时间日期相关常用的类以及创建方法。
  2. 备注 创建方法
  3. Timestamp 时刻数据 to_datetimeTimestamp
  4. DatetimeIndex Timestamp的索引 to_datetimedate_rangeDatetimeIndex
  5. Period 时期数据 Period
  6. PeriodIndex Period period_range PeriodIndex
  7. Pandas 中关于时间序列最常见的类型就是时间戳(Timestamp)了,创建时间戳的方法有很多种,我们分别来看一看。

 基本方法

  1. pd.Timestamp(2018,5,21)
  2. Out[12]: Timestamp('2018-05-21 00:00:00')
  3. pd.Timestamp('2018-5-21')
  4. Out[13]: Timestamp('2018-05-21 00:00:00')
  5. #除了时间戳之外,另一个常见的结构是时间跨度(Period)。
  6. pd.Period("2018-01")
  7. Out[14]: Period('2018-01', 'M')
  8. pd.Period("2018-05", freq="D")
  9. Out[15]: Period('2018-05-01', 'D')
  10. #索引后会自动强制转为为 DatetimeIndex 和 PeriodIndex。
  11. dates = [pd.Timestamp("2018-05-01"), pd.Timestamp("2018-05-02"), pd.Timestamp("2018-05-03"), pd.Timestamp("2018-05-04")]
  12. ts = pd.Series(data=["Tom", "Bob", "Mary", "James"], index=dates)
  13. ts.index
  14. Out[16]: DatetimeIndex(['2018-05-01', '2018-05-02', '2018-05-03', '2018-05-04'], dtype='datetime64[ns]', freq=None)
  15. periods = [pd.Period("2018-01"), pd.Period("2018-02"), pd.Period("2018-03"), pd.Period("2018-4")]
  16. ts = pd.Series(data=["Tom", "Bob", "Mary", "James"], index=periods)
  17. ts.index
  18. Out[17]: PeriodIndex(['2018-01', '2018-02', '2018-03', '2018-04'], dtype='period[M]', freq='M')

二、转换时间戳

  你可能会想到,我们经常要和文本数据(字符串)打交道,能否快速将文本数据转为时间戳呢?
  答案是可以的,通过 to_datetime 能快速将字符串转换为时间戳。当传递一个Series时,它会返回一个Series(具有相同的索引),而类似列表的则转换为DatetimeIndex。

  1. pd.to_datetime(pd.Series(["Jul 31, 2018", "2018-05-10", None]))
  2. Out[18]:
  3. 0 2018-07-31
  4. 1 2018-05-10
  5. 2 NaT
  6. dtype: datetime64[ns]
  7. pd.to_datetime(["2005/11/23", "2010.12.31"])
  8. Out[19]: DatetimeIndex(['2005-11-23', '2010-12-31'], dtype='datetime64[ns]', freq=None)
  9. #除了可以将文本数据转为时间戳外,还可以将 unix 时间转为时间戳。
  10. pd.to_datetime([1349720105, 1349806505, 1349892905], unit="s")
  11. Out[20]:
  12. DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
  13. '2012-10-10 18:15:05'],
  14. dtype='datetime64[ns]', freq=None)
  15. pd.to_datetime([1349720105100, 1349720105200, 1349720105300], unit="ms")
  16. Out[21]:
  17. DatetimeIndex(['2012-10-08 18:15:05.100000', '2012-10-08 18:15:05.200000',
  18. '2012-10-08 18:15:05.300000'],
  19. dtype='datetime64[ns]', freq=None)

三、生成时间戳范围

  有时候,我们可能想要生成某个范围内的时间戳。例如,我想要生成 "2018-6-26" 这一天之后的8天时间戳,如何完成呢?我们可以使用 date_range 和 bdate_range 来完成时间戳范围的生成。

  1. pd.date_range("2018-6-26", periods=8)
  2. Out[22]:
  3. DatetimeIndex(['2018-06-26', '2018-06-27', '2018-06-28', '2018-06-29',
  4. '2018-06-30', '2018-07-01', '2018-07-02', '2018-07-03'],
  5. dtype='datetime64[ns]', freq='D')
  6. pd.bdate_range("2018-6-26", periods=8)
  7. Out[23]:
  8. DatetimeIndex(['2018-06-26', '2018-06-27', '2018-06-28', '2018-06-29',
  9. '2018-07-02', '2018-07-03', '2018-07-04', '2018-07-05'],
  10. dtype='datetime64[ns]', freq='B')
  11. #可以看出,date_range 默认使用的频率是 日历日,而 bdate_range 默认使用的频率是 营业日。当然了,我们可以自己指定频率,比如,我们可以按周来生成时间戳范围。
  12. pd.date_range("2018-6-26", periods=8, freq="W")
  13. Out[24]:
  14. DatetimeIndex(['2018-07-01', '2018-07-08', '2018-07-15', '2018-07-22',
  15. '2018-07-29', '2018-08-05', '2018-08-12', '2018-08-19'],
  16. dtype='datetime64[ns]', freq='W-SUN') 

四. DatetimeIndex

DatetimeIndex 的主要作用是之一是用作 Pandas 对象的索引,使用它作为索引除了拥有普通索引对象的所
有基本功能外,还拥有简化频率处理的高级时间序列方法。

  1. rng = pd.date_range("2018-6-24", periods=4, freq="W")
  2. ts = pd.Series(range(len(rng)), index=rng)
  3. ts
  4. Out[25]:
  5. 2018-06-24 0
  6. 2018-07-01 1
  7. 2018-07-08 2
  8. 2018-07-15 3
  9. Freq: W-SUN, dtype: int64
  10. # 通过日期访问数据
  11. ts["2018-07-08"]
  12. Out[26]: 2
  13. # 通过日期区间访问数据切片
  14. ts["2018-07-08": "2018-07-22"]
  15. Out[27]:
  16. 2018-07-08 2
  17. 2018-07-15 3
  18. Freq: W-SUN, dtype: int64
  19. #传入年份
  20. ts["2018"]
  21. Out[28]:
  22. 2018-06-24 0
  23. 2018-07-01 1
  24. 2018-07-08 2
  25. 2018-07-15 3
  26. Freq: W-SUN, dtype: int64
  27. # 传入年份和月份
  28. ts["2018-07"]
  29. Out[29]:
  30. 2018-07-01 1
  31. 2018-07-08 2
  32. 2018-07-15 3
  33. Freq: W-SUN, dtype: int64
  34. #除了可以使用字符串对 DateTimeIndex 进行索引外,还可以使用 datetime(日期时间)对象来进行索引。
  35. from datetime import datetime
  36. ts[datetime(2018, 7, 8) : datetime(2018, 7, 22)]
  37. Out[30]:
  38. 2018-07-08 2
  39. 2018-07-15 3
  40. Freq: W-SUN, dtype: int64
  41. # 获取年份
  42. ts.index.year
  43. Out[31]: Int64Index([2018, 2018, 2018, 2018], dtype='int64')
  44. # 获取星期几
  45. ts.index.dayofweek
  46. Out[32]: Int64Index([6, 6, 6, 6], dtype='int64')
  47. # 获取一年中的第几个星期
  48. ts.index.weekofyear
  49. Out[33]: Int64Index([25, 26, 27, 28], dtype='int64')

五.DateOffset对象

DateOffset 从名称中就可以看出来是要做日期偏移的,它的参数与 dateutil.relativedelta基本相同,工作方式如下:

  1. from pandas.tseries.offsets import *
  2. d = pd.Timestamp("2018-06-25")
  3. d + DateOffset(weeks=2, days=5)
  4. Out[34]: Timestamp('2018-07-14 00:00:00')
  5. #除了可以使用 DateOffset 完成上面的功能外,还可以使用偏移量实例来完成。
  6. d + Week(2) + Day(5)
  7. Out[35]: Timestamp('2018-07-14 00:00:00')

六、与时间序列相关的方法

在做时间序列相关的工作时,经常要对时间做一些移动/滞后、频率转换、采样等相关操作,我们来看下这些操作如何使用吧。

  6.1 移动

  如果你想移动或滞后时间序列,你可以使用 shift 方法。

  可以看到,Series 所有的值都都移动了 2 个距离。如果不想移动值,而是移动日期索引,可以使用 freq 参数,它可以接受一个 DateOffset 类或其他 timedelta 类对象或一个 offset 别名,所有别名详细介绍见:Offset Aliases(http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases)。

  1. ts.shift(2)
  2. Out[36]:
  3. 2018-06-24 NaN
  4. 2018-07-01 NaN
  5. 2018-07-08 0.0
  6. 2018-07-15 1.0
  7. Freq: W-SUN, dtype: float64
  8. ts.shift(2, freq=Day())
  9. Out[37]:
  10. 2018-06-26 0
  11. 2018-07-03 1
  12. 2018-07-10 2
  13. 2018-07-17 3
  14. Freq: W-TUE, dtype: int64
  15. #可以看到,现在日期索引移动了 2 天的间隔。通过 tshift 同样可以达到相同的效果。
  16. ts.tshift(2, freq=Day())
  17. Out[38]:
  18. 2018-06-26 0
  19. 2018-07-03 1
  20. 2018-07-10 2
  21. 2018-07-17 3
  22. Freq: W-TUE, dtype: int64

  6.2频率转换

  频率转换可以使用 asfreq 函数来实现。下面演示了将频率由周转为了天。

  1. ts.asfreq(Day())
  2. Out[39]:
  3. 2018-06-24 0.0
  4. 2018-06-25 NaN
  5. 2018-06-26 NaN
  6. 2018-06-27 NaN
  7. 2018-06-28 NaN
  8. 2018-06-29 NaN
  9. 2018-06-30 NaN
  10. 2018-07-01 1.0
  11. 2018-07-02 NaN
  12. 2018-07-03 NaN
  13. 2018-07-04 NaN
  14. 2018-07-05 NaN
  15. 2018-07-06 NaN
  16. 2018-07-07 NaN
  17. 2018-07-08 2.0
  18. 2018-07-09 NaN
  19. 2018-07-10 NaN
  20. 2018-07-11 NaN
  21. 2018-07-12 NaN
  22. 2018-07-13 NaN
  23. 2018-07-14 NaN
  24. 2018-07-15 3.0
  25. Freq: D, dtype: float64
  26. #聪明的你会发现出现了缺失值,因此 Pandas 为你提供了 method 参数来填充缺失值。几种不同的填充方法参考 Pandas 缺失值处理 中 fillna 介绍。
  27. ts.asfreq(Day(), method="pad")
  28. Out[40]:
  29. 2018-06-24 0
  30. 2018-06-25 0
  31. 2018-06-26 0
  32. 2018-06-27 0
  33. 2018-06-28 0
  34. 2018-06-29 0
  35. 2018-06-30 0
  36. 2018-07-01 1
  37. 2018-07-02 1
  38. 2018-07-03 1
  39. 2018-07-04 1
  40. 2018-07-05 1
  41. 2018-07-06 1
  42. 2018-07-07 1
  43. 2018-07-08 2
  44. 2018-07-09 2
  45. 2018-07-10 2
  46. 2018-07-11 2
  47. 2018-07-12 2
  48. 2018-07-13 2
  49. 2018-07-14 2
  50. 2018-07-15 3
  51. Freq: D, dtype: int64

  6.3 重采样

  resample 表示根据日期维度进行数据聚合,可以按照分钟、小时、工作日、周、月、年等来作为日期维度,更多的日期维度见 Offset Aliases(http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases)。这里我们先以月来作为时间维度来进行聚合。

  1. # 求出每个月的数值之和
  2. ts.resample("1M").sum()
  3. Out[41]:
  4. 2018-06-30 0
  5. 2018-07-31 6
  6. Freq: M, dtype: int64
  7. # 求出每个月的数值平均值
  8. ts.resample("1M").mean()
  9. Out[42]:
  10. 2018-06-30 0
  11. 2018-07-31 2
  12. Freq: M, dtype: int64

案例

  1. import pandas as pd
  2. from matplotlib import pyplot as plt
  3. import numpy as np
  4.  
  5. pd.set_option('display.max_columns',None)
  6.  
  7. df = pd.read_csv('911.csv')
  8.  
  9. df.timeStamp = pd.to_datetime(df.timeStamp) #时间字符串转时间格式
  10.  
  11. df.set_index('timeStamp',inplace=True) #设置时间格式为索引
  12. # print(df.head())
  13.  
  14. #统计出911数据中不同月份电话次数
  15. count_by_month = df.resample('M').count()['title']
  16. print(count_by_month)
  17.  
  18. #画图
  19. _x = count_by_month.index
  20. _y = count_by_month.values
  21.  
  22. plt.figure(figsize=(15,8),dpi=80)
  23.  
  24. plt.plot(range(len(_x)),_y)
  25.  
  26. plt.xticks(range(len(_x)),_x.strftime('%Y-%m-%d'),rotation=45)
  27.  
  28. plt.show()

示例1:统计出911数据中不同月份电话次数的变化情况

  1. import pandas as pd
  2. from matplotlib import pyplot as plt
  3. import numpy as np
  4.  
  5. pd.set_option('display.max_columns',None)
  6.  
  7. df = pd.read_csv('911.csv')
  8. #把时间字符串转化为时间类型设置为索引
  9. df.timeStamp = pd.to_datetime(df.timeStamp)
  10.  
  11. #添加列,表示分类
  12. temp_list = df.title.str.split(':').tolist()
  13. cate_list = [i[0] for i in temp_list]
  14. df['cate'] = pd.DataFrame(np.array(cate_list).reshape(df.shape[0],1))
  15.  
  16. df.set_index('timeStamp',inplace=True)
  17.  
  18. plt.figure(figsize=(15, 8), dpi=80)
  19.  
  20. #分组
  21. for group_name,group_data in df.groupby(by='cate'):
  22. #对不同的分类都进行绘图
  23. count_by_month = group_data.resample('M').count()['title']
  24. # 画图
  25. _x = count_by_month.index
  26. _y = count_by_month.values
  27. plt.plot(range(len(_x)),_y,label=group_name)
  28.  
  29. plt.xticks(range(len(_x)), _x.strftime('%Y-%m-%d'), rotation=45)
  30.  
  31. plt.legend(loc='best')
  32. plt.show()

示例2:统计出911数据中不同月份不同类型的电话的次数的变化情况

  1. import pandas as pd
  2. from matplotlib import pyplot as plt
  3.  
  4. pd.set_option('display.max_columns',None)
  5.  
  6. df = pd.read_csv('PM2.5/BeijingPM20100101_20151231.csv')
  7. # print(df.head())
  8.  
  9. #把分开的时间字符串通过periodIndex的方法转化为pandas的时间类型
  10. period = pd.PeriodIndex(year=df.year,month=df.month,day=df.day,hour=df.hour,freq='H')
  11. df['datetime'] = period
  12. print(df.head(10))
  13.  
  14. #把datetime设置为索引
  15. df.set_index('datetime',inplace=True)
  16.  
  17. #进行降采样
  18. df = df.resample('7D').mean()
  19.  
  20. #处理缺失值,删除缺失数据
  21. # data = df['PM_US Post'].dropna()
  22. # china_data = df['PM_Nongzhanguan'].dropna()
  23. data = df['PM_US Post']
  24. china_data = df['PM_Nongzhanguan']
  25.  
  26. #画图
  27. _x = data.index
  28. _y = data.values
  29.  
  30. _x_china = china_data.index
  31. _y_china = china_data.values
  32.  
  33. plt.figure(figsize=(13,8),dpi=80)
  34.  
  35. plt.plot(range(len(_x)),_y,label='US_POST',alpha=0.7)
  36. plt.plot(range(len(_x_china)),_y_china,label='CN_POST',alpha=0.7)
  37.  
  38. plt.xticks(range(0,len(_x_china),10),list(_x_china.strftime('%Y%m%d'))[::10],rotation=45)
  39.  
  40. plt.show()

示例3:绘制美国和中国PM2.5随时间的变化情况

 

Pandas系列(六)-时间序列详解的更多相关文章

  1. nginx高性能WEB服务器系列之四配置文件详解

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  2. mongo 3.4分片集群系列之六:详解配置数据库

    这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...

  3. mongo 3.4分片集群系列之五:详解平衡器

    这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...

  4. Hexo系列(二) 配置文件详解

    Hexo 是一款优秀的博客框架,在使用 Hexo 搭建一个属于自己的博客网站后,我们还需要对其进行配置,使得 Hexo 更能满足自己的需求 这里所说的配置文件,是位于站点根目录下的 _config.y ...

  5. css3系列之transform详解translate

    translate translate这个参数的,是transform 身上的,那么它有什么用呢? 其实他的作用很简单,就是平移,参考自己的位置来平移 translate() translateX() ...

  6. ThreeJS系列1_CinematicCameraJS插件详解

    ThreeJS系列1_CinematicCameraJS插件详解 接着上篇 ThreeJS系列1_CinematicCameraJS插件介绍 看属性的来龙去脉 看方法作用 通过调整属性查看效果 总结 ...

  7. [js高手之路] html5 canvas系列教程 - 状态详解(save与restore)

    本文内容与路径([js高手之路] html5 canvas系列教程 - 开始路径beginPath与关闭路径closePath详解)是canvas中比较重要的概念.掌握理解他们是做出复杂canvas动 ...

  8. Android组件系列----Activity组件详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...

  9. C++ list容器系列功能函数详解

    C++ list函数详解 首先说下eclipse工具下怎样debug:方法:你先要设置好断点,然后以Debug方式启动你的应用程序,不要用run的方式,当程序运行到你的断点位置时就会停住,也会提示你进 ...

随机推荐

  1. c/c++ 多线程 多个线程等待同一个线程的一次性事件

    多线程 多个线程等待一个线程的一次性事件 背景:从多个线程访问同一个std::future,也就是多个线程都在等待同一个线程的结果,这时怎么处理. 办法:由于std::future只能被调用一次get ...

  2. c/c++ 多线程 一个线程等待某种事件发生

    多线程 一个线程等待某种事件发生 背景:某个线程在能够完成其任务之前可能需要等待另一个线程完成其任务. 例如:坐夜间列车,为了能够不坐过站, 1,整夜保持清醒,但是这样你就会非常累,不能够睡觉. 2, ...

  3. c/c++ linux 进程间通信系列5,使用信号量

    linux 进程间通信系列5,使用信号量 信号量的工作原理: 由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的: P(sv):如果sv的值大于零,就给它减1:如果 ...

  4. configparser_配置解析器

    configparser:配置解析器 import configparser config = configparser.ConfigParser() #配置文件 config[', 'Compres ...

  5. linux环境快速编译安装python3.6

    一.下载python3源码包 cd /tmp/wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz 二.下载python3编译的依 ...

  6. Python开发【内置模块篇】collections

    namedtuple namedtuple是一个函数,它用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素. 这样一来,我们用name ...

  7. 洛谷P2243 电路维修

    题目地址 转化为图论问题 对于每个交叉点(X,Y)抽象成节点.与它相邻的四个点中,可以直接连线的边权为0,否则边权为1. 用死了的SPFA解决图论问题. #include <cstring> ...

  8. Linux 中改变默认文件打开方式的位置

    全局的打开方式, /etc/gnome/defaults.list 个人的打开方式, -/.local/share/applications/mimeapps.list 当这两个文件不一致时,优先采用 ...

  9. ELK的安装

    首先得安装好Elasticsearch.Kibana和Logstash(这里全部使用rpm安装的是6.4.2版本,而且都是单机安装,暂时没有考虑分布式安装.) 服务器内存要求至少为4G,下图为运行起来 ...

  10. Centos6.6安装docker

    今天在虚拟机上体验一下docker, 操作系统:Centos6.6 内核版本:2.6 1. https://download.csdn.net/download/dujiaoyang000/10872 ...