介绍

Pandas 是非常著名的开源数据处理库,我们可以通过它完成对数据集进行快速读取、转换、过滤、分析等一系列操作。同样,Pandas 已经被证明为是非常强大的用于处理时间序列数据的工具。本节将介绍所有 Pandas 在时间序列数据上的处理方法。

知识点

  • 创建时间对象
  • 时间索引对象
  • 时间算术方法

创建时间对象

在 Pandas 中关于时间序列的常见对象有 6 种,分别是 Timestamp(时间戳)、DatetimeIndex(时间戳索引)、Period(时间段)、PeriodIndex(时间段索引)、以时间为元素的 Series 和以及以时间索引的 DataFrame。本小节学习如何创建以上对象。

创建时间戳

Timestamp 时间戳表示时间轴上的某一点,以下不同代码都可以生成相同时间戳。

创建时间为 2018 年 10 月 1 日的时间戳。

import pandas as pd

pd.Timestamp(2018, 10, 1)

也可以使创建的时间精确到时分秒。

pd.Timestamp("2018-10-1 10:00:1")
from datetime import datetime

pd.Timestamp(datetime(2018, 10, 1))

创建时间段

Period 时间段表示时间轴上的某一区间,以下代码都可以生成相同时间段。

pd.Period('2018-10')

Period() 函数后面通常有两个参数,第二个 freq 参数决定时间段的分割长度。

创建频率为日的时间段。

pd.Period('2018-10', freq='D')

创建时间元素的 Series

Pandas 中常用 to_datetime() 函数可以创建以时间为元素的 Series。

创建一个 Series,以三个时间的字符串作为元素。

df = ['2018-08-01', '2018-09-01', '2018-10-01']
pd.to_datetime(df)

可以使用多种方法创建时间元素的 Series。

df = pd.Series(['Sep 30, 2018', '2018-10-1', None])
pd.to_datetime(df)
df = pd.DataFrame({'year': [2017, 2018],
'month': [9, 10],
'day': [30, 1],
'hour': [23, 0]})
pd.to_datetime(df)

创建时间索引

要生成带有时间戳的索引,可以使用 DatetimeIndex() 构造函数,并传入列表或 Series 对象:

dates = ['2018-08-01', '2018-09-01', '2018-10-01']
index = pd.DatetimeIndex(dates)
index

实际运用中我们经常需要大量的的时间戳的索引。可以使用 date_range()bdate_range() 来批量创建相同时间间隔的时间戳索引。

创建以 2018 年 9 月 30 日为开始的 250 条时间索引,相邻索引间隔时间长度为一个月。

index = pd.date_range('2018-9-30', periods=250, freq='M')
index

创建以 2018 年 10 月 1 日为开始的 111 条时间索引,相邻索引间隔时间长度为一个工作日。

index = pd.bdate_range('2018-10-1', periods=111)
index

date_range()bdate_range() 中可以巧妙使用 start,end, periods,freq 等参数的各种组合轻松批量创建时间索引。

在 2017 年 10 月 1 日到 2018 年 10 月 1 日间,每隔一周创建一条索引。

start = datetime(2017, 10, 1)
end = datetime(2018, 10, 1)
rng = pd.date_range(start, end, freq='W')
rng

从 2018 年 10 月 1 日向前每隔一个工作日创建一条索引,共 250 条。

pd.bdate_range(end=end, periods=250)

同理,时间段也能作为索引使用,需要用到 period_range()

从 2018 年 9 月 30 日向后创建 666 条索引,相邻索引间隔时间长度为一天。

pi = pd.period_range('2018-9-30', periods=666)
pi

创建以时间为索引的 Series 对象

以时间为索引的 Series 对象指的是在该 Series 中,元素的索引不再是 1、2、3、4、5……这样的序号,而是有序的日期和时间。

import numpy as np

dates = [pd.Timestamp('2018-08-01'), pd.Timestamp('2018-09-01'),
pd.Timestamp('2018-10-01')] # 创建三个时间元素。
ts = pd.Series(np.random.randn(3), dates) # 创建索引值为随机数的 Series 对象。
ts

同样,时间段也能作为索引。

periods = [pd.Period('2018-08'), pd.Period('2018-09'), pd.Period('2018-10')]
ts = pd.Series(np.random.randn(3), periods)
ts

我们可以批量创建索引后再创建以时间为索引的 Series 对象。创建索引值为随机数的 Series 对象,长度与 rng 长度相同。

ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts

时间段也能作为索引创建 DataFrame 对象。在 2017 年第一季度和 2018 年第四季度之间每隔一个季度创建一条索引。

prng = pd.period_range('2017Q1', '2018Q4', freq='Q-NOV')
# 行索引为时间段索引,列索引为 A。
ps = pd.DataFrame(np.random.rand(len(prng)), columns=[
'A'], index=prng)
ps

时间索引对象处理

以时间戳为索引的 Series、DataFrame 对象具有与普通列表近乎相同的操作,且更具智能化。

查找

简单查找。

ts

查找前 10 条索引记录。

ts[:10]

每隔 1 条记录查找 1 条索引记录。

ts[::2]

查找第 0、2、6 条索引记录。

ts[[0, 2, 6]]

基于时间索引的精确查找。查找索引为 2018 年 9 月 30 日的值。

ts["09/30/2018"]
ts[datetime(2018, 9, 30)]

基于索引的范围查找。查找索引时间在 2017 年内的所有记录。

ts["2017"]

查找索引时间在 2018 年 9 月内的所有记录。

ts["2018-9"]

以时间段为索引的 DataFrame 对象的查找规则与以时间戳的相同。

ps

2018 年的第一个季度规定为 2017 年的 12 月初到 2018 年的 2 月末。

查找 2017 年内的所有季度的记录。

ps["2017"]

查找 2017 年 12 月 31 日前的所有季度的记录。

ps[:datetime(2017, 12, 31)]

查找 2018 年 6 月内的所有季度的记录。

ps["2018-06"]

切片

使用 truncate() 切下 2017 年 11 月 26 日与 2018 年 4 月 29 日间的记录。

ts.truncate(before='11/26/2017', after='4/29/2018')

移动

将时间索引 Series 中的值向后和向前移动。其方法是 shift()

ts = ts[:5]  # 取前 5 条数据方便观察。
ts

将元素列向下移动一条。

ts.shift(1)

除了元素可以被移动,索引本身也能被移动,需要加上 freq 参数。将索引列向上移动一条:

ts.shift(1, freq='W')

重采样

重采样可以通俗得理解为改变时间索引的个数,通过增大或减小相邻索引的时间间隔以达到减小或增加索引数量的效果,在 Pandas 中使用 resample() 函数。

下采样:增大时间间隔,减少记录的数量。创建从 2018 年 10 月 1 日开始的日间隔索引的 Series 。

rng = pd.date_range('10/1/2018', periods=10, freq='D')
ts = pd.Series(np.random.randint(0, 50, len(rng)), index=rng)
ts

原先索引的日间隔被扩大为周间隔,并以周末为索引采样点,采样点的索引值为所有未被索引值的和。

ts.resample('W').sum()

同样也能使采样点的索引值为所有未被索引值的平均值。

ts.resample('W').mean()

使用 ohlc() 函数对所用未被采样值进行统计。

ts.resample('W').ohlc()

上采样:减小时间间隔频率,增加记录的数量。

原来间隔为日的索引列,间隔被缩小成 12 小时,增加采样点的值为空值。

ts.resample('12H').asfreq()

ffill() 函数可以将新增的索引值以相邻的前一条索引值进行填充。

ts.resample('12H').ffill()

时间的算术方法

常用时间的算术规则

下表是 Pandas 内建的一些时间类,常用于时间索引的位移。

首先要导入 pandas.tseries.offsets 模块,Pandas 所有常用时间类都在该模块中。

d = pd.Timestamp(2018, 10, 1, 10, 1, 1)
d

使用 DateOffset() 实现时间戳位移。

向后移动一个月零两天。

from pandas.tseries.offsets import DateOffset

d + DateOffset(months=1, days=2)

也可以用时间戳加减常用时间类以实现时间戳位移。向前移动 10 个工作日。

from pandas.tseries.offsets import BDay

d - 10 * BDay()

向后移动一个月末。

from pandas.tseries.offsets import BMonthEnd

d + BMonthEnd()

个性化定制日期。虽然日历规定年末是 12 月,加入参数后相当于人为规定 2 月是年末。

向后移动到上两个年末。

from pandas.tseries.offsets import YearEnd

d + YearEnd(month=2)

向前移动到上一个周四。

from pandas.tseries.offsets import Week

d - Week(weekday=4)

可以使用 rollforward() 将指定时间向前或向后移动到一个制定常用时间类的时间戳上。将时间移动到下一个月末:

offset = BMonthEnd()
offset.rollforward(d)

将时间移动到上一个月末。

offset.rollback(d)

偏移也同样适用于时间索引

rng

所有的时间索引向后移动两日。

rng + DateOffset(days=2)

所有的时间索引向后移动两个工作日。

rng + 2*BDay()

所有的时间索引向后移动 15 分钟。

from pandas.tseries.offsets import Minute

rng + Minute(15)

下列是常用时间系列频率参数,上面小节经常出现,现在以一个表格作详细说明。

参数名 说明
B 工作日频率
C 定制工作日频率
D 日历日频率
W 每周频率
M 月结束频率
SM 半月结束频率(15 个月和月末)
BM 业务月末频率
CBM 定制业务月末频率
MS 月起始频率
sMs 半月起始频率(第 1 和 15)
BMS 业务月开始频率
CBMS 定制商业月份开始频率
Q 四分频结束频率
BQ 业务四分之一频率
QS 四分频启动频率
BQS 业务季开始频率
A 年结束频率
BA 业务年结束频率
AS 年起始频率
BAS 业务年开始频率
BH 工作时间频率
H 每小时频率
T, min 分钟频率
S 次频
L, ms 毫秒
U, uS 微秒
N 纳秒

使用常用频率参数组合创建时间索引。

创建 10 条以 2018 年 10 月 1 日为开始,间隔为 1 天 1 小时 1 分钟 10 微秒的时间索引。

pd.date_range("2018-10-1", periods=10, freq='1D1H1min10U')

以下频率参数可以指定后缀以达到改变默认间隔点的效果。

创建 10 条以 2018 年 10 月 1 日为开始,间隔为每周三的时间索引。

pd.date_range("2018-10-1", periods=10, freq='W-WED')

在使用特定频率(MonthEnd,MonthBegin,WeekEnd 等)的参数时,如果起始时间是刚好在频率点上,使用 n 参数可以决定是否让该点参与计算。

n=1 时参与计算。

from pandas.tseries.offsets import MonthBegin

pd.Timestamp('2018-10-1') + MonthBegin(n=1)

n=0 时不参与计算。

pd.Timestamp('2018-10-1') + MonthBegin(n=0)

下采样聚合

下采样中的聚合是指下采样后,对未被采样到的点进行的一系列计算。

创建 100 个日历日为时间索引的 DataFrame,将其以月频率下采样。

df = pd.DataFrame(np.random.rand(100, 3),
index=pd.date_range('10/1/2018', freq='D', periods=100),
columns=['A', 'B', 'C'])
r = df.resample('M')
r

对未采样点求和,结果保存在采样点的值中。

r.sum()

在下采样后也能进行查找操作。选择 A、C 列后取均值计算。

r[['A', 'C']].mean()

使用 agg() 同时进行不同的计算。对采样结果进行取和与取均值计算。

r.agg([np.sum, np.mean])

选择 A 列,同时进行取和,取均值,取标准差计算。

r['A'].agg([np.sum, np.mean, np.std]

对 A 列求和与标准差,对 B 列求均值与标准差。

r.agg({'A': ['sum', 'std'], 'B': ['mean', 'std']})

总结

本章节介绍了 Pandas 对时间序列数据的基本处理操作。重点演示了时间的创建、时间索引对象的处理、时间的相关计算。当然,文中对这些方法的介绍依然还不够详细。如果你需要在实际工作中进行更复杂的时间数据处理,还需要深刻理解文中的基本演示,改编或组合出更高级的功能,这样才能发挥出 Pandas 的强大作用。

Python——Pandas 时间序列数据处理的更多相关文章

  1. Python Pandas 时间序列双轴折线图

    时间序列pv-gmv双轴折线图 import numpy as np import pandas as pd import matplotlib.pyplot as plt n = 12 date_s ...

  2. python ---Pandas时间序列:生成指定范围的日期

    引入包 import pandas as pd import numpy as np 1.生成指定范围的日期 print pd.date_range('11/1/2018','11/9/2018') ...

  3. Python pandas快速入门

    Python pandas快速入门2017年03月14日 17:17:52 青盏 阅读数:14292 标签: python numpy 数据分析 更多 个人分类: machine learning 来 ...

  4. Pandas时间序列

    Pandas时间序列 pandas 提供了一组标准的时间序列处理工具和数据算法 数据类型及操作 Python 标准库的 datetime datetime 模块中的 datetime. time. c ...

  5. python pandas.Series&&DataFrame&& set_index&reset_index

    参考CookBook :http://pandas.pydata.org/pandas-docs/stable/cookbook.html Pandas set_index&reset_ind ...

  6. Pandas 时间序列处理

    目录 Pandas 时间序列处理 1 Python 的日期和时间处理 1.1 常用模块 1.2 字符串和 datetime 转换 2 Pandas 的时间处理及操作 2.1 创建与基础操作 2.2 时 ...

  7. pandas | 使用pandas进行数据处理——DataFrame篇

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是pandas数据处理专题的第二篇文章,我们一起来聊聊pandas当中最重要的数据结构--DataFrame. 上一篇文章当中我们介绍了 ...

  8. python & pandas链接mysql数据库

    Python&pandas与mysql连接 1.python 与mysql 连接及操作,直接上代码,简单直接高效: import MySQLdb try: conn = MySQLdb.con ...

  9. python学习_数据处理编程实例(二)

    在上一节python学习_数据处理编程实例(二)的基础上数据发生了变化,文件中除了学生的成绩外,新增了学生姓名和出生年月的信息,因此将要成变成:分别根据姓名输出每个学生的无重复的前三个最好成绩和出生年 ...

随机推荐

  1. Kmeans应用

    1.思路 应用Kmeans聚类时,需要首先确定k值,如果k是未知的,需要先确定簇的数量.其方法可以使用拐点法.轮廓系数法(k>=2).间隔统计量法.若k是已知的,可以直接调用sklearn子模块 ...

  2. java内存机制 垃圾回收

    gc机制一 1.JVM的gc概述 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc ...

  3. CF_448D 二分

    给定n m k n和m为一个矩阵的行和列,都从1开始,矩阵的每个元素的值即为 i*j(行*列),求里面第k个数 还想找什么规律,发现虽然矩阵里面很有规律,但是n 和m在不断变化 根本不好找 其实元素从 ...

  4. Javascript里EQ、NE、GT、LT、GE、LE含义

    EQ 就是 EQUAL等于 NE就是 NOT EQUAL不等于 GT 就是 GREATER THAN大于  LT 就是 LESS THAN小于 GE 就是 GREATER THAN OR EQUAL ...

  5. 吴裕雄--天生自然Django框架开发笔记:Django Nginx+uwsgi 安装配置

    Django Nginx+uwsgi 安装配置 使用 python manage.py runserver 来运行服务器.这只适用测试环境中使用. 正式发布的服务,需要一个可以稳定而持续的服务器,比如 ...

  6. [BJDCTF2020]Mark loves cat

    0x00 知识点 GitHack读取源码 $$会导致变量覆盖漏洞 0x01解题 dirsearch扫描一下,发现/.git目录,用githack获取一下源码. <?php include 'fl ...

  7. 洛谷 P1020 导弹拦截

    题目传送门 解题思路: 其实就是求一遍最长不上升子序列和最长上升子序列 AC代码: #include<iostream> #include<cstdio> #include&l ...

  8. Java Web应用的加载过程

    在介绍Spring IoC和MVC的加载前,用这篇小文章简单地记录下,最简单的web应用的加载过程. 一.从最简单的web应用出发 使用Eclipse直接创建一个Dynamic Web Project ...

  9. 【每日Scrum】第四天冲刺

    一.计划会议内容 连接数据库报错,解决问题中. 二.任务看板 三.scrum讨论照片 四.产品的状态 无 五.任务燃尽图  

  10. P3370 【模板】字符串哈希 题解

    地址:https://www.luogu.org/problem/P3370 求不同字符串的数量 这题用set也可以过,但是hash更高大上嘛. 哈希其实就是将一个字符串映射成一个值,并且要让这些值不 ...