目录

  • 一、Pandas 时间序列数据处理
  • 1.1 知识点
  • 二、创建时间对象
  • 2.1 创建时间戳
  • 2.2 创建时间段
  • 2.3 创建时间元素的 Series
  • 2.4 创建时间索引
  • 2.4.1 大量的的时间戳的索引
  • 2.5 创建以时间为索引的 Series 对象
  • 三、时间索引对象处理
  • 3.1 时间戳为索引——查找
  • 3.2 时间段为索引——查找
  • 3.3 切片
  • 3.4 移动
  • 3.5 重采样
  • 3.5.1 下采样
  • 3.5.2 上采样
  • 四、时间的算术方法
  • 4.1 常用时间的算术规则
  • 4.1.1 偏移也同样适用于时间索引
  • 4.1.2 常用时间系列频率参数
  • 4.1.3 频率参数指定后缀
  • 4.2 下采样聚合
  • 五、实验总结


 

一、Pandas 时间序列数据处理

Pandas 是非常著名的开源数据处理库

  • 我们可以通过它完成对数据集进行快速读取、转换、过滤、分析等一系列操作。
  • 同样,Pandas 已经被证明为是非常强大的用于处理时间序列数据的工具

 

1.1 知识点

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

 
 
 

二、创建时间对象

在 Pandas 中关于时间序列的常见对象有 6 种,分别是 :

  1. Timestamp(时间戳)
  2. DatetimeIndex(时间戳索引)
  3. Period(时间段)
  4. PeriodIndex(时间段索引)
  5. 以时间为元素的 Series 和
  6. 以时间索引的 DataFrame
     

2.1 创建时间戳

  • Timestamp时间戳表示:时间轴上的某一点

以下不同代码都可以生成相同时间戳。

  1. 创建时间为 2018 年 10 月 1 日的时间戳。
import pandas as pd
pd.Timestamp(2018, 10, 1)
  1. 也可以使创建的时间精确到时分秒。
pd.Timestamp("2018-10-1 10:00:1")



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

 

2.2 创建时间段

  • Period 时间段表示:时间轴上的某一区间

以下代码都可以生成相同时间段
1.

pd.Period('2018-10')

Period() 函数后面:

  • 通常有两个参数,第二个 freq 参数决定时间段的分割长度
  1. 创建频率为日的时间段。
pd.Period('2018-10', freq='D')

 

2.3 创建时间元素的 Series

Pandas 中常用 to_datetime() 函数:

  • 可以创建以时间为元素Series
  1. 创建一个 Series,以三个时间的字符串作为元素
df = ['2018-08-01', '2018-09-01', '2018-10-01']
pd.to_datetime(df)
  1. 可以使用多种方法创建时间元素的 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)

 
 

2.4 创建时间索引

要生成带有时间戳的索引

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

 

2.4.1 大量的的时间戳的索引

实际运用中我们经常需要大量的的时间戳的索引。

  1. 创建以 2018 年 9 月 30 日为开始250 条时间索引
  • 相邻索引间隔时间长度为一个月
index = pd.date_range('2018-9-30', periods=250, freq='M')
index

时间序列数据的导入python 时间序列数据处理方法_python

  1. 创建以 2018 年 10 月 1 日为开始111 条时间索引
  • 相邻索引间隔时间长度为一个工作日
index = pd.bdate_range('2018-10-1', periods=111)
index

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_02


 
date_range() 和 ·bdate_range() 中:

  • 可以巧妙使用 startendperiodsfreq参数的各种组合
  • 轻松批量创建时间索引
     
  1. 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

时间序列数据的导入python 时间序列数据处理方法_算法_03


 

  1. 2018 年 10 月 1 日向前隔一个工作日创建一条索引,共 250 条
pd.bdate_range(end=end, periods=250)

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_04

 
同理,时间段也能作为索引使用

 

  1. 2018 年 9 月 30 日向后创建 666 条索引,相邻索引间隔时间长度为一天
pi = pd.period_range('2018-9-30', periods=666)
pi

时间序列数据的导入python 时间序列数据处理方法_算法_05


 
 

2.5 创建以时间为索引的 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

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_06

  1. 同样,时间段也能作为索引。
periods = [pd.Period('2018-08'), pd.Period('2018-09'), pd.Period('2018-10')]
ts = pd.Series(np.random.randn(3), periods)
ts

时间序列数据的导入python 时间序列数据处理方法_python_07

  1. 我们可以批量创建索引后再 创建以时间为索引的 Series 对象
  • 创建索引值为随机数的 Series 对象
  • 长度与 rng 长度相同
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts

时间序列数据的导入python 时间序列数据处理方法_数据分析_08

 

  1. 时间段也能作为索引创建 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

时间序列数据的导入python 时间序列数据处理方法_算法_09


 
 
 

三、时间索引对象处理

时间戳为索引SeriesDataFrame 对象

  • 具有与普通列表近乎相同的操作
  • 且更具智能化

 

3.1 时间戳为索引——查找

  1. 简单查找
ts
  1. 查找前 10 条索引记录
ts[:10]

时间序列数据的导入python 时间序列数据处理方法_pandas_10

  1. 隔 1 条记录查找 1 条索引记录。
ts[::2]

时间序列数据的导入python 时间序列数据处理方法_pandas_11

  1. 查找第 0、2、6 条索引记录。
ts[[0, 2, 6]]

 

  1. 基于时间索引的精确查找
  • 查找索引为 2018 年 9 月 30 日的值。
ts["09/30/2018"]
ts[datetime(2018, 9, 30)]

 

  1. 基于索引的范围查找。
  • 查找索引时间在 2017 年内的所有记录。
ts["2017"]

时间序列数据的导入python 时间序列数据处理方法_python_12

  • 查找索引时间在 2018 年 9 月内的所有记录。
ts["2018-9"]

时间序列数据的导入python 时间序列数据处理方法_算法_13


 

 

3.2 时间段为索引——查找

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

时间序列数据的导入python 时间序列数据处理方法_python_14


 

  1. 2018 年的第一个季度规定为 2017 年的 12 月初到 2018 年的 2 月末
  • 查找 2017 年内的所有季度的记录。
ps["2017"]

时间序列数据的导入python 时间序列数据处理方法_python_15

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

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

时间序列数据的导入python 时间序列数据处理方法_pandas_16

 

  1. 查找 2018 年 6 月内的所有季度的记录。
ps["2018-06"]

时间序列数据的导入python 时间序列数据处理方法_python_17


 
 

3.3 切片

使用 truncate()

  • 切下 2017 年 11 月 26 日与 2018 年 4 月 29 日间的记录。
ts.truncate(before='11/26/2017', after='4/29/2018')

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_18


 
 

3.4 移动

时间索引 Series 中的值向后和向前移动。

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

时间序列数据的导入python 时间序列数据处理方法_算法_19

  1. 将元素列向下移动一条。
ts.shift(1)

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_20

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

 

  1. 将索引列向上移动一条
ts.shift(1, freq='W')

时间序列数据的导入python 时间序列数据处理方法_python_21


 
 

3.5 重采样

重采样可以通俗得理解为改变时间索引的个数

  • 通过增大或减小相邻索引的时间间隔以达到减小或增加索引数量的效果
  • 在 Pandas 中使用 resample() 函数

 

3.5.1 下采样

增大时间间隔,减少记录的数量。

  • 创建从 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

时间序列数据的导入python 时间序列数据处理方法_算法_22


 

  1. 原先索引的日间隔被扩大为周间隔
  • 并以周末为索引采样点,采样点的索引值为所有未被索引值的和
ts.resample('W').sum()

时间序列数据的导入python 时间序列数据处理方法_数据分析_23


 

  1. 同样也能使 采样点的索引值为 所有未被索引值的平均值
ts.resample('W').mean()

时间序列数据的导入python 时间序列数据处理方法_python_24

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

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

时间序列数据的导入python 时间序列数据处理方法_python_25


 
 

3.5.2 上采样

减小时间间隔频率,增加记录的数量

  1. 原来间隔为日的索引列,间隔被缩小成 12 小时
  • 增加采样点的值为空值
ts.resample('12H').asfreq()

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_26

 
2. ffill() 函数

  • 可以将新增的索引值以相邻的前一条索引值进行填充
ts.resample('12H').ffill()

时间序列数据的导入python 时间序列数据处理方法_pandas_27


 
 
 

四、时间的算术方法

4.1 常用时间的算术规则

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

时间序列数据的导入python 时间序列数据处理方法_数据分析_28

  1. 首先要导入 pandas.tseries.offsets 模块
  • Pandas 所有常用时间类都在该模块中
from pandas.tseries.offsets import DateOffset

 

  1. 使用 DateOffset() 实现时间戳位移
  • 向后移动一个月零两天。
d = pd.Timestamp(2018, 10, 1, 10, 1, 1)
d
from pandas.tseries.offsets import DateOffset
d + DateOffset(months=1, days=2)

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_29


 

  1. 也可以用时间戳加减
  • 常用时间类以实现时间戳位移
  • 向前移动 10 个工作日
from pandas.tseries.offsets import BDay
d - 10 * BDay()

时间序列数据的导入python 时间序列数据处理方法_算法_30


 

  1. 向后移动一个月末
from pandas.tseries.offsets import BMonthEnd
d + BMonthEnd()

时间序列数据的导入python 时间序列数据处理方法_数据分析_31

 

  1. 个性化定制日期。
  • 虽然日历规定年末是 12 月,加入参数后相当于人为规定 2 月是年末
  • 向后移动到上两个年末
from pandas.tseries.offsets import YearEnd
d + YearEnd(month=2)

 

  1. 向前移动上一个周四
from pandas.tseries.offsets import Week
d - Week(weekday=4)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-21wPEHpa-1619944756240)(https://dn-simplecloud.shiyanlou.com/courses/uid1117915-20210502-1619941822031)]

 

  1. 可以使用 rollforward()
  • 将指定时间向前或向后移动到一个指定常用时间类的时间戳
  • 将时间移动到下一个月末
offset = BMonthEnd()
offset.rollforward(d)

时间序列数据的导入python 时间序列数据处理方法_pandas_32

 

  1. 将时间移动到上一个月末
offset.rollback(d)

时间序列数据的导入python 时间序列数据处理方法_数据分析_33


 

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

rng
  1. 所有的时间索引向后移动两日
rng + DateOffset(days=2)

时间序列数据的导入python 时间序列数据处理方法_算法_34


 

  1. 所有的时间索引向后移动两个工作日
rng + 2*BDay()

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_35

 

  1. 所有的时间索引向后移动 15 分钟
from pandas.tseries.offsets import Minute
rng + Minute(15)

时间序列数据的导入python 时间序列数据处理方法_pandas_36


 
 

4.1.2 常用时间系列频率参数

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

参数名

说明

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

纳秒

 

  1. 使用常用频率参数组合创建时间索引。
  • 创建 10 条以 2018 年 10 月 1 日为开始
  • 间隔为 1 天 1 小时 1 分钟 10 微秒的时间索引
pd.date_range("2018-10-1", periods=10, freq='1D1H1min10U')

时间序列数据的导入python 时间序列数据处理方法_pandas_37

 

4.1.3 频率参数指定后缀

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

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_38

  1. 创建 10 条以 2018 年 10 月 1 日为开始,间隔为每周三的时间索引。
pd.date_range("2018-10-1", periods=10, freq='W-WED')

时间序列数据的导入python 时间序列数据处理方法_算法_39


 

  1. n 参数
    在使用特定频率(MonthEnd,MonthBegin,WeekEnd 等)的参数
  • 如果起始时间是刚好在频率点
  • 使用 n 参数可以决定是否让该点参与计算
  • n=1 时参与计算。
from pandas.tseries.offsets import MonthBegin
pd.Timestamp('2018-10-1') + MonthBegin(n=1)

时间序列数据的导入python 时间序列数据处理方法_pandas_40


 

  • n=0 时不参与计算
pd.Timestamp('2018-10-1') + MonthBegin(n=0)

时间序列数据的导入python 时间序列数据处理方法_pandas_41


 
 

4.2 下采样聚合

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

  1. 创建 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

 

  1. 对未采样点求和
  • 结果保存在采样点的值中。
r.sum()

时间序列数据的导入python 时间序列数据处理方法_python_42


 

  1. 在下采样后也能进行查找操作
  • 选择 A、C 列后取均值计算。
r[['A', 'C']].mean()

时间序列数据的导入python 时间序列数据处理方法_数据分析_43

 

  1. 使用 agg() 同时进行不同的计算
  • 对采样结果进行取和与取均值计算
r.agg([np.sum, np.mean])

时间序列数据的导入python 时间序列数据处理方法_时间序列数据的导入python_44

 

  1. 选择 A 列,同时进行取和,取均值,取标准差计算
r['A'].agg([np.sum, np.mean, np.std])

时间序列数据的导入python 时间序列数据处理方法_pandas_45

 

  1. 对 A 列求和与标准差,对 B 列求均值与标准差
r.agg({'A': ['sum', 'std'], 'B': ['mean', 'std']})

 
 
 

五、实验总结

  • Pandas 对时间序列数据的基本处理操作。
  1. 时间的创建
  2. 时间索引对象的处理
  3. 时间的相关计算。
     
  • 基本演示,改编或组合出更高级的功能,这样才能发挥出 Pandas 的强大作用。