时序数据

import numpy as np
import pandas as pd

一、时序中的基本对象

(1) 时间戳 (Date times): pandas 中称为 Timestamp,一系列的时间戳可以组成 DatetimeIndex ,将它放到 Series 中后, Series 的类型就变为了 datetime64[ns] ,如果有涉及时区则为 datetime64[ns, tz] ,其中tz是timezone的简写

(2) 时间差(Time deltas): pandas中利用 Timedelta 来表示,一系列的时间差就组成了 TimedeltaIndex , 而将它放到 Series 中后, Series 的类型就变为了 timedelta64[ns]

(3) 时间段(Time spans): 在 pandas 利用 Period 来表示,一系列的时间段就组成了 PeriodIndex , 而将它放到 Series 中后, Series 的类型就变为了 Period

(4) 日期偏置(Date offsets): pandas中利用DateOffset

二、时间戳

1. Timestamp的构造与属性

(1) pd.Timestamp

ts = pd.Timestamp('2020/1/1')
ts
Timestamp('2020-01-01 00:00:00')
ts = pd.Timestamp('2020-1-1 08:10:30')
ts
Timestamp('2020-01-01 08:10:30')

(2) year, month, day, hour, min, second 可以获取具体的数值

在 pandas 中,时间戳的最小精度为纳秒 ns

ts.year
2020

(3) pd.Timestamp.max 和 pd.Timestamp.min获取时间戳表示的范围

pd.Timestamp.max
Timestamp('2262-04-11 23:47:16.854775807')
pd.Timestamp.min
Timestamp('1677-09-21 00:12:43.145225')
pd.Timestamp.max.year - pd.Timestamp.min.year
585

2. Datetime序列的生成

(1) to_datetime把一列时间戳格式的对象转换成为 datetime64[ns] 类型的时间序列

pd.to_datetime(['2020-1-1', '2020-1-3', '2020-1-6'])
DatetimeIndex(['2020-01-01', '2020-01-03', '2020-01-06'], dtype='datetime64[ns]', freq=None)
df = pd.read_csv('data/learn_pandas.csv')
s = pd.to_datetime(df.Test_Date)
s.head()
0   2019-10-05
1   2019-09-04
2   2019-09-12
3   2020-01-03
4   2019-11-06
Name: Test_Date, dtype: datetime64[ns]

时间戳的格式不满足转换时,可以强制使用 format 进行匹配

temp = pd.to_datetime(['2020\\1\\1','2020\\1\\3'],format='%Y\\%m\\%d')
temp
DatetimeIndex(['2020-01-01', '2020-01-03'], dtype='datetime64[ns]', freq=None)

上面由于传入的是列表,而非 pandas 内部的 Series ,因此返回的是 DatetimeIndex ,如果想要转为 datetime64[ns] 的序列,需要显式用 Series 转化

pd.Series(temp).head()
0   2020-01-01
1   2020-01-03
dtype: datetime64[ns]

表的多列时间属性拼接转为时间序列的 to_datetime 操作

此时的列名必须和以下给定的时间关键词列名一致,也就是year, month, day, hour, min, second

df_date_cols = pd.DataFrame({'year': [2020, 2020],'month': [1, 1],'day': [1, 2], 'hour': [10, 20],'minute': [30, 50],'second': [20, 40]})
pd.to_datetime(df_date_cols)
0   2020-01-01 10:30:20
1   2020-01-02 20:50:40
dtype: datetime64[ns]

(2) date_range 是一种生成连续间隔时间的一种方法

参数:开始或结束日期如果作为端点则它会被包含

start: 开始时间

end: 结束时间

freq: 时间间隔

periods: 时间戳个数

pd.date_range('2020-1-1','2020-1-21', freq='10D') # 包含
DatetimeIndex(['2020-01-01', '2020-01-11', '2020-01-21'], dtype='datetime64[ns]', freq='10D')
pd.date_range('2020-1-1','2020-2-28', freq='10D')
DatetimeIndex(['2020-01-01', '2020-01-11', '2020-01-21', '2020-01-31','2020-02-10', '2020-02-20'],dtype='datetime64[ns]', freq='10D')
 pd.date_range('2020-1-1','2020-2-28', periods=6) # 由于结束日期无法取到,freq不为10天
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-12 14:24:00','2020-01-24 04:48:00', '2020-02-04 19:12:00','2020-02-16 09:36:00', '2020-02-28 00:00:00'],dtype='datetime64[ns]', freq=None)

3. 练一练

Timestamp 上定义了一个 value 属性,其返回的整数值代表了从1970年1月1日零点到给定时间戳相差的纳秒数,请利用这个属性构造一个随机生成给定日期区间内日期序列的函数。

**思路:**首先测试一下value的使用,得到的是一个值,使用pd.to_date可以将其转换为日期,我们只需要将日期区间的value值取出,然后使用random.sample生成随机序列,再转换为日期,即可得到我们想要的结果

import random
ts = pd.Timestamp('2020/1/1')
pd.to_datetime(ts.value)
Timestamp('2020-01-04 07:08:36')
pd.to_datetime(1578121716000000000)
Timestamp('2020-01-04 07:08:36')

解答

def dt_random(date_start,date_end,n):start = date_start.valueend = date_end.values = pd.Series(random.sample(range(int(start/1000000000),int(end/1000000000)),n))*1000000000#我们只需要到秒的数据,所以需要将数值转换一下return pd.to_datetime(s.tolist())
dt_random(pd.to_datetime('2020-1-1'),pd.to_datetime('2020-1-21'),4)
DatetimeIndex(['2020-01-03 13:41:52', '2020-01-04 23:21:12','2020-01-11 10:30:12', '2020-01-06 10:45:15'],dtype='datetime64[ns]', freq=None)

(3) asfreq:改变序列采样频率的方法

根据给定的 freq 对序列进行类似于 reindex 的操作

s = pd.Series(np.random.rand(5),index=pd.to_datetime(['2020-1-%d'%i for i in range(1,10,2)]))
s.head()
2020-01-01    0.647305
2020-01-03    0.818546
2020-01-05    0.770349
2020-01-07    0.985936
2020-01-09    0.243881
dtype: float64
s.asfreq('D').head()
2020-01-01    0.647305
2020-01-02         NaN
2020-01-03    0.818546
2020-01-04         NaN
2020-01-05    0.770349
Freq: D, dtype: float64
s.asfreq('12H').head()
2020-01-01 00:00:00    0.647305
2020-01-01 12:00:00         NaN
2020-01-02 00:00:00         NaN
2020-01-02 12:00:00         NaN
2020-01-03 00:00:00    0.818546
Freq: 12H, dtype: float64

【前面提到了 datetime64[ns] 本质上可以理解为一个大整数,对于一个该类型的序列,可以使用 max, min, mean ,来取得最大时间戳、最小时间戳和“平均”时间戳。】

4. dt对象

(1) 取出时间相关的属性

包括: date, time, year, month, day, hour, minute, second, microsecond, nanosecond, dayofweek, dayofyear, weekofyear, daysinmonth, quarter ,其中 daysinmonth, quarter 分别表示该月一共有几天和季度

s = pd.Series(pd.date_range('2020-1-1','2020-1-3', freq='D'))
s.dt.date
0    2020-01-01
1    2020-01-02
2    2020-01-03
dtype: object
s.dt.time
0    00:00:00
1    00:00:00
2    00:00:00
dtype: object
s.dt.daysinmonth
0    31
1    31
2    31
dtype: int64
s.dt.dayofweek #返回了周中的星期情况,周一为0、周二为1
0    2
1    3
2    4
dtype: int64
s.dt.month_name() #返回英文的月名
0    January
1    January
2    January
dtype: object
s.dt.day_name() #返回英文的星期名
0    Wednesday
1     Thursday
2       Friday
dtype: object

(2) 判断操作

用于测试是否为月/季/年的第一天或者最后一天

s.dt.is_year_start # 还可选 is_quarter/month_start
0     True
1    False
2    False
dtype: bool
s.dt.is_year_end # 还可选 is_quarter/month_end
0    False
1    False
2    False
dtype: bool

(3) 取整操作

包含 round, ceil, floor ,它们的公共参数为 freq ,常用的包括 H, min, S (小时、分钟、秒)

s = pd.Series(pd.date_range('2020-1-1 20:35:00','2020-1-1 22:35:00',freq='45min'))
s
0   2020-01-01 20:35:00
1   2020-01-01 21:20:00
2   2020-01-01 22:05:00
dtype: datetime64[ns]
s.dt.round('1H') #四舍五入
0   2020-01-01 21:00:00
1   2020-01-01 21:00:00
2   2020-01-01 22:00:00
dtype: datetime64[ns]
s.dt.ceil('1H') #向后取整
0   2020-01-01 21:00:00
1   2020-01-01 22:00:00
2   2020-01-01 23:00:00
dtype: datetime64[ns]
s.dt.floor('1H') #向前取整
0   2020-01-01 20:00:00
1   2020-01-01 21:00:00
2   2020-01-01 22:00:00
dtype: datetime64[ns]

5. 时间戳的切片与索引

一般而言,时间戳序列作为索引使用。如果想要选出某个子时间戳序列,第一类方法是利用 dt 对象和布尔条件联合使用,另一种方式是利用切片,后者常用于连续时间戳

s = pd.Series(np.random.randint(2,size=366),index=pd.date_range('2020-01-01','2020-12-31'))
idx = pd.Series(s.index).dt
s.head()
2020-01-01    0
2020-01-02    1
2020-01-03    1
2020-01-04    1
2020-01-05    0
Freq: D, dtype: int32

Example1:每月的第一天或者最后一天

s[(idx.is_month_start|idx.is_month_end).values].head()
2020-01-01    0
2020-01-31    1
2020-02-01    1
2020-02-29    1
2020-03-01    0
dtype: int32

Example2:双休日

 s[idx.dayofweek.isin([5,6]).values].head()
2020-01-04    1
2020-01-05    0
2020-01-11    0
2020-01-12    1
2020-01-18    0
dtype: int32

Example3:取出单日值

s['2020-01-01']
0
s['20200101'] # 自动转换标准格式
0

Example4:取出七月

s['2020-07'].head()
2020-07-01    0
2020-07-02    0
2020-07-03    1
2020-07-04    0
2020-07-05    0
Freq: D, dtype: int32

Example5:取出5月初至7月15日

s['2020-05':'2020-7-15'].head()
2020-05-01    0
2020-05-02    1
2020-05-03    1
2020-05-04    1
2020-05-05    0
Freq: D, dtype: int32
s['2020-05':'2020-7-15'].tail()
2020-07-11    0
2020-07-12    0
2020-07-13    1
2020-07-14    0
2020-07-15    1
Freq: D, dtype: int32

三、时间差

1. Timedelta的生成

(1) pd.Timedelta构造时间差

pd.Timestamp('20200102 08:00:00')-pd.Timestamp('20200101 07:35:00')
Timedelta('1 days 00:25:00')
pd.Timedelta(days=1, minutes=25) # 需要注意加s
Timedelta('1 days 00:25:00')
 pd.Timedelta('1 days 25 minutes') # 字符串生成
Timedelta('1 days 00:25:00')

(2) pd.to_timedelta生成时间差序列,类型为 timedelta64

s = pd.to_timedelta(df.Time_Record)
s.head()
0   0 days 00:04:34
1   0 days 00:04:20
2   0 days 00:05:22
3   0 days 00:04:08
4   0 days 00:05:22
Name: Time_Record, dtype: timedelta64[ns]

(3) timedelta_range生成时间差序列

pd.timedelta_range('0s', '1000s', freq='6min')
TimedeltaIndex(['0 days 00:00:00', '0 days 00:06:00', '0 days 00:12:00'], dtype='timedelta64[ns]', freq='6T')
pd.timedelta_range('0s', '1000s', periods=3)
TimedeltaIndex(['0 days 00:00:00', '0 days 00:08:20', '0 days 00:16:40'], dtype='timedelta64[ns]', freq=None)

(4) dt对象

属性包括 days, seconds, mircroseconds, nanoseconds ,它们分别返回了对应的时间差特征。需要注意的是,这里的 seconds 不是指单纯的秒,而是对天数取余后剩余的秒数

s.dt.seconds.head()
0    274
1    260
2    322
3    248
4    322
Name: Time_Record, dtype: int64

total_seconds:不对天数取余而直接对应秒数

s.dt.total_seconds().head()
0    274.0
1    260.0
2    322.0
3    248.0
4    322.0
Name: Time_Record, dtype: float64

取整函数

pd.to_timedelta(df.Time_Record).dt.round('min').head()
0   0 days 00:05:00
1   0 days 00:04:00
2   0 days 00:05:00
3   0 days 00:04:00
4   0 days 00:05:00
Name: Time_Record, dtype: timedelta64[ns]

2. Timedelta的运算

支持三类运算:与标量的乘法运算、与时间戳的加减法运算、与时间差的加减法与除法运算

td1 = pd.Timedelta(days=1)
td2 = pd.Timedelta(days=3)
ts = pd.Timestamp('20200101')
td1 * 2
Timedelta('2 days 00:00:00')
td2 - td1
Timedelta('2 days 00:00:00')
ts + td1
Timestamp('2020-01-02 00:00:00')
ts - td1
Timestamp('2019-12-31 00:00:00')

这些运算都可以移植到时间差的序列上:

td1 = pd.timedelta_range(start='1 days', periods=5)
td2 = pd.timedelta_range(start='12 hours',freq='2H',periods=5)
ts = pd.date_range('20200101', '20200105')
td1 * 5
TimedeltaIndex(['5 days', '10 days', '15 days', '20 days', '25 days'], dtype='timedelta64[ns]', freq='5D')
td1 * pd.Series(list(range(5))) # 逐个相乘
0    0 days
1    2 days
2    6 days
3   12 days
4   20 days
dtype: timedelta64[ns]
td1 - td2
TimedeltaIndex(['0 days 12:00:00', '1 days 10:00:00', '2 days 08:00:00','3 days 06:00:00', '4 days 04:00:00'],dtype='timedelta64[ns]', freq=None)
td1 + pd.Timestamp('20200101')
DatetimeIndex(['2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05','2020-01-06'],dtype='datetime64[ns]', freq='D')
td1 + ts # 逐个相加
DatetimeIndex(['2020-01-02', '2020-01-04', '2020-01-06', '2020-01-08','2020-01-10'],dtype='datetime64[ns]', freq=None)

四、日期偏置

1. Offset对象

日期偏置是一种和日历相关的特殊时间差,求2020年9月第一个周一的日期,以及如何求2020年9月7日后的第30个工作日是哪一天

pd.Timestamp('20200831') + pd.offsets.WeekOfMonth(week=0,weekday=0)
Timestamp('2020-09-07 00:00:00')
pd.Timestamp('20200907') + pd.offsets.BDay(30)
Timestamp('2020-10-19 00:00:00')

Offset 对象在 pd.offsets 中被定义,使用 + 时获取离其最近的下一个日期,当使用 - 时获取离其最近的上一个日期

pd.Timestamp('20200831') - pd.offsets.WeekOfMonth(week=0,weekday=0)
Timestamp('2020-08-03 00:00:00')
pd.Timestamp('20200907') - pd.offsets.BDay(30)
Timestamp('2020-07-27 00:00:00')
pd.Timestamp('20200907') + pd.offsets.MonthEnd()
Timestamp('2020-09-30 00:00:00')

cday: holidays, weekmask 参数能够分别对自定义的日期和星期进行过滤,前者传入了需要过滤的日期列表,后者传入的是三个字母的星期缩写构成的星期字符串,其作用是只保留字符串中出现的星期

my_filter = pd.offsets.CDay(n=1,weekmask='Wed Fri',holidays=['20200109'])
dr = pd.date_range('20200108', '20200111')
dr.to_series().dt.dayofweek
2020-01-08    2
2020-01-09    3
2020-01-10    4
2020-01-11    5
Freq: D, dtype: int64
[i + my_filter for i in dr]
[Timestamp('2020-01-10 00:00:00'),Timestamp('2020-01-10 00:00:00'),Timestamp('2020-01-15 00:00:00'),Timestamp('2020-01-15 00:00:00')]

上面的例子中,n 表示增加一天 CDay , dr 中的第一天为 20200108 ,但由于下一天 20200109 被排除了,并且 20200110 是合法的周五,因此转为 20200110 ,其他后面的日期处理类似

在当前版本下由于一些 bug ,不要使用 Day 级别以下的 Offset 对象,比如 Hour, Second 等,请使用对应的 Timedelta 对象来代替。

2. 偏置字符串

date_range 的 freq 取值可用 Offset 对象,每一个 Offset 对象绑定了日期偏置字符串( frequencies strings/offset aliases ),可以指定 Offset 对应的字符串来替代使用

pd.date_range('20200101','20200331', freq='MS') # 月初
DatetimeIndex(['2020-01-01', '2020-02-01', '2020-03-01'], dtype='datetime64[ns]', freq='MS')
pd.date_range('20200101','20200331', freq='M') # 月末
DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31'], dtype='datetime64[ns]', freq='M')
pd.date_range('20200101','20200110', freq='B') # 工作日
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-06','2020-01-07', '2020-01-08', '2020-01-09', '2020-01-10'],dtype='datetime64[ns]', freq='B')
pd.date_range('20200101','20200201', freq='W-MON') # 周一
DatetimeIndex(['2020-01-06', '2020-01-13', '2020-01-20', '2020-01-27'], dtype='datetime64[ns]', freq='W-MON')
 pd.date_range('20200101','20200201',freq='WOM-1MON')# 每月第一个周一
DatetimeIndex(['2020-01-06'], dtype='datetime64[ns]', freq='WOM-1MON')

等价于offset对象:

pd.date_range('20200101','20200331',freq=pd.offsets.MonthBegin())# 月初
DatetimeIndex(['2020-01-01', '2020-02-01', '2020-03-01'], dtype='datetime64[ns]', freq='MS')
pd.date_range('20200101','20200331',freq=pd.offsets.MonthEnd()) #月末
DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31'], dtype='datetime64[ns]', freq='M')
pd.date_range('20200101','20200110', freq=pd.offsets.BDay()) #工作日
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-06','2020-01-07', '2020-01-08', '2020-01-09', '2020-01-10'],dtype='datetime64[ns]', freq='B')
pd.date_range('20200101','20200201',freq=pd.offsets.CDay(weekmask='Mon')) #周一
DatetimeIndex(['2020-01-06', '2020-01-13', '2020-01-20', '2020-01-27'], dtype='datetime64[ns]', freq='C')
pd.date_range('20200101','20200201', freq=pd.offsets.WeekOfMonth(week=0,weekday=0))# 每月第一个周一
DatetimeIndex(['2020-01-06'], dtype='datetime64[ns]', freq='WOM-1MON')

五、时序中的滑窗与分组

1.滑动窗口

把滑动窗口用 freq 关键词代替

案例: 在股票市场中有一个指标为 BOLL 指标,它由中轨线、上轨线、下轨线这三根线构成,具体的计算方法分别是 N 日均值线、 N 日均值加两倍 N 日标准差线、 N 日均值减两倍 N 日标准差线。利用 rolling 对象计算 N=30 的 BOLL 指标可以如下写出

import matplotlib.pyplot as plt
idx = pd.date_range('20200101', '20201231', freq='B')
np.random.seed(2020)
data = np.random.randint(-1,2,len(idx)).cumsum() # 随机游动构造模拟序列
s = pd.Series(data,index=idx)
s.head()
2020-01-01   -1
2020-01-02   -2
2020-01-03   -1
2020-01-06   -1
2020-01-07   -2
Freq: B, dtype: int32
r = s.rolling('30D')
plt.plot(s)
plt.title('BOLL LINES')
plt.plot(r.mean())
plt.plot(r.mean()+r.std()*2)
plt.plot(r.mean()-r.std()*2)
[<matplotlib.lines.Line2D at 0x2da04159a310>]

shift 函数作用在 datetime64 为索引的序列上时,可以指定 freq 单位进行滑动

s.shift(freq='50D').head()
2020-02-20   -1
2020-02-21   -2
2020-02-22   -1
2020-02-25   -1
2020-02-26   -2
dtype: int32

datetime64[ns] 的序列进行 diff 后就能够得到 timedelta64[ns] 的序列,方便观察有序时间序列的间隔

my_series = pd.Series(s.index)
my_series.head()
0   2020-01-01
1   2020-01-02
2   2020-01-03
3   2020-01-06
4   2020-01-07
dtype: datetime64[ns]
my_series.diff(1).head()
0      NaT
1   1 days
2   1 days
3   3 days
4   1 days
dtype: timedelta64[ns]

2. 重采样

重采样对象 resample 和第四章中分组对象 groupby 的用法类似,前者是针对时间序列的分组计算而设计的分组对象

s.resample('10D').mean().head()
2020-01-01   -2.000000
2020-01-11   -3.166667
2020-01-21   -3.625000
2020-01-31   -4.000000
2020-02-10   -0.375000
Freq: 10D, dtype: float64

如果没有内置定义的处理函数,可以通过 apply 方法自定义

s.resample('10D').apply(lambda x:x.max()-x.min()).head() # 极差
2020-01-01    3
2020-01-11    4
2020-01-21    4
2020-01-31    2
2020-02-10    4
Freq: 10D, dtype: int32

边界问题

resample 中要特别注意组边界值的处理情况,默认情况下起始值的计算方法是从最小值时间戳对应日期的午夜 00:00:00 开始增加 freq ,直到不超过该最小时间戳的最大时间戳,由此对应的时间戳为起始值,然后每次累加 freq 参数作为分割结点进行分组,区间情况为左闭右开

idx = pd.date_range('20200101 8:26:35', '20200101 9:31:58', freq='77s')
data = np.random.randint(-1,2,len(idx)).cumsum()
s = pd.Series(data,index=idx)
s.head()
2020-01-01 08:26:35   -1
2020-01-01 08:27:52   -1
2020-01-01 08:29:09   -2
2020-01-01 08:30:26   -3
2020-01-01 08:31:43   -4
Freq: 77S, dtype: int32

第一个组起始值为 08:24:00 ,其是从当天0点增加72个 freq=7 min 得到的,如果再增加一个 freq 则超出了序列的最小时间戳 08:26:35

s.resample('7min').mean().head()
2020-01-01 08:24:00   -1.750000
2020-01-01 08:31:00   -2.600000
2020-01-01 08:38:00   -2.166667
2020-01-01 08:45:00    0.200000
2020-01-01 08:52:00    2.833333
Freq: 7T, dtype: float64

指定 origin 参数为 start :从序列的最小时间戳开始依次增加 freq 进行分组

s.resample('7min', origin='start').mean().head()
2020-01-01 08:26:35   -2.333333
2020-01-01 08:33:35   -2.400000
2020-01-01 08:40:35   -1.333333
2020-01-01 08:47:35    1.200000
2020-01-01 08:54:35    3.166667
Freq: 7T, dtype: float64

索引取值

索引一般是取组的第一个时间戳,但 M, A, Q, BM, BA, BQ, W 这七个是取对应区间的最后一个时间戳:

s = pd.Series(np.random.randint(2,size=366),index=pd.date_range('2020-01-01','2020-12-31'))
s.resample('M').mean().head()
2020-01-31    0.548387
2020-02-29    0.620690
2020-03-31    0.483871
2020-04-30    0.466667
2020-05-31    0.483871
Freq: M, dtype: float64
s.resample('MS').mean().head() # 结果一样,但索引不同
2020-01-01    0.548387
2020-02-01    0.620690
2020-03-01    0.483871
2020-04-01    0.466667
2020-05-01    0.483871
Freq: MS, dtype: float64

六、练习

1. 太阳辐射数据集

df1 = pd.read_csv('data/solar.csv', usecols=['Data','Time','Radiation','Temperature'])
df1.head(2)
Data Time Radiation Temperature
0 9/29/2016 12:00:00 AM 23:55:26 1.21 48
1 9/29/2016 12:00:00 AM 23:50:23 1.21 48

1. 将 Datetime, Time 合并为一个时间列 Datetime ,同时把它作为索引后排序

思路: 首先查看存储的类型,发现Data和Time都是object类型,我们需要取出Data的年月日,然后与Time拼接,最后再设置为索引,并排序

df = df1.copy()
df.dtypes
Data            object
Time            object
Radiation      float64
Temperature      int64
dtype: object
#创建Datetime字段
df['Datetime'] = pd.to_datetime(df['Data']+df['Time'])
#设置为索引
df = df.set_index('Datetime')
#索引排序
df = df.sort_index()
df.head()
Data Time Radiation Temperature
Datetime
2016-09-01 00:00:08 9/1/2016 12:00:00 AM 00:00:08 2.58 51
2016-09-01 00:05:10 9/1/2016 12:00:00 AM 00:05:10 2.83 51
2016-09-01 00:20:06 9/1/2016 12:00:00 AM 00:20:06 2.16 51
2016-09-01 00:25:05 9/1/2016 12:00:00 AM 00:25:05 2.21 51
2016-09-01 00:30:09 9/1/2016 12:00:00 AM 00:30:09 2.25 51

2.每条记录时间的间隔显然并不一致,请解决如下问题:

a. 找出间隔时间的前三个最大值所对应的三组时间戳。

df2 = df.reset_index()
#求时间间隔
df2['date_diff'] = df2['Datetime'].diff().dt.total_seconds()
#按照时间间隔字段排序
df2 = df2.sort_values('date_diff',ascending = False)
#取出排名前三的时间戳
df2.head(3)['Datetime']
25923   2016-12-08 11:10:42
24522   2016-12-01 00:00:02
7417    2016-10-01 00:00:19
Name: Datetime, dtype: datetime64[ns]

思考: 最终结果是需要取到时间戳组,新建一列偏移值列

df3 = df.reset_index()
#将索引向前+1
new = pd.DataFrame(df3['Datetime'])
new.index = new.index+1
#求时间间隔
df3['date_diff'] = df3['Datetime'].diff().dt.total_seconds()
#增加diff求值的开始列
df3['date_start'] = new['Datetime']
#按照时间间隔字段排序
df3 = df3.sort_values('date_diff',ascending = False)
#求出排前3的组
df3[['date_start','Datetime']].head(3)
date_start Datetime
25923 2016-12-05 20:45:53 2016-12-08 11:10:42
24522 2016-11-29 19:05:02 2016-12-01 00:00:02
7417 2016-09-29 23:55:26 2016-10-01 00:00:19

b.是否存在一个大致的范围,使得绝大多数的间隔时间都落在这个区间中?如果存在,请对此范围内的样本间隔秒数画出柱状图,设置 bins=50 。

**思考:**用分位数去获取值

d = df3['date_diff']
data = d.mask((d>d.quantile(0.99))|(d<d.quantile(0.01)))
pl = plt.hist(data, bins=50)

3.求如下指标对应的 Series :

a.温度与辐射量的6小时滑动相关系数

思考: 索引参数必须是Datetime

r = df['Radiation'].rolling('6H').corr(df['Temperature'])
r.tail(5)
Datetime
2016-12-31 23:35:02    0.416187
2016-12-31 23:40:01    0.416565
2016-12-31 23:45:04    0.328574
2016-12-31 23:50:03    0.261883
2016-12-31 23:55:01    0.262406
dtype: float64

b.以三点、九点、十五点、二十一点为分割,该观测所在时间区间的温度均值序列

df['Temperature'].resample('6H', origin='3:00:00').mean().head()
Datetime
2016-08-31 21:00:00    51.218750
2016-09-01 03:00:00    50.033333
2016-09-01 09:00:00    59.379310
2016-09-01 15:00:00    57.984375
2016-09-01 21:00:00    51.393939
Freq: 6H, Name: Temperature, dtype: float64

c.每个观测6小时前的辐射量(一般而言不会恰好取到,此时取最近时间戳对应的辐射量)

思路: 先找到6小时前的时间,然后再匹配时间间隔最近的值

new = df.index.shift(freq='-6H')
int_loc = [df.index.get_loc(i, method='nearest') for i in new]
r = df['Radiation'].iloc[int_loc]
r.tail()
Datetime
2016-12-31 17:35:01    15.96
2016-12-31 17:40:06    11.98
2016-12-31 17:45:02     9.33
2016-12-31 17:50:01     8.49
2016-12-31 17:55:02     5.84
Name: Radiation, dtype: float64

Day11-Python时序数据(DataWhale)相关推荐

  1. python使用pandas通过聚合获取时序数据的最后一个指标数据(例如长度指标、时间指标)生成标签并与原表连接(join)进行不同标签特征的可视化分析

    python使用pandas通过聚合获取时序数据的最后一个指标数据(例如长度指标.时间指标)生成标签并与原表连接(join)进行不同标签特征的可视化分析 目录

  2. 手把手教你用Python玩转时序数据,从采样、预测到聚类

    本文经AI新媒体量子位(公众号 ID: QbitAI)授权转载,转载请联系出处 本文约1800字,建议阅读5分钟 如果你有朝一日碰到了时序数据,该怎么用Python搞定它呢? 时序数据,也就是时间序列 ...

  3. Datawhale组队-Pandas(下)时序数据(打卡)

    Pandas可以处理任何领域的时序数据(time series),使用Numpy的datetime64 和timedelta64 类型,Pandas整合了来自其他Python库的大量功能,如Sciki ...

  4. python数据预测代码_手把手教你用Python玩转时序数据,从采样、预测到聚类丨代码...

    原标题:手把手教你用Python玩转时序数据,从采样.预测到聚类丨代码 原作 Arnaud Zinflou 郭一璞 编译 时序数据,也就是时间序列的数据. 像股票价格.每日天气.体重变化这一类,都是时 ...

  5. python 特征工程_[译] 基于时序数据的特征工程 --- Python实现

    基于时序数据的回归预测问题,在工作中经常遇到的.它与一般的监督学习的回归模型的区别在于数据本身是基于时序的.而常用的时序预测模型,比如arima等,添加其他特征时又不方便,不得不求助于经典的监督学习预 ...

  6. 时序分析 44 -- 时序数据转为空间数据 (三) 格拉姆角场 python 实践 (上)

    格拉姆角场 python实践 时序预测问题是一个古老的问题了,在笔者关于时序分析的系列中已经介绍了多种时序预测分析技术和方法.本篇我们将使用一种新的思路来进行时序预测:对金融数据进行GAF(格拉姆角场 ...

  7. python处理时序数据总结

    pandas处理时序数据容易出错,经过多次摸索之后总结如下: #先读取数据 data=pd.read_csv(fs, header=None, sep=';',index_col=False,enco ...

  8. python读取时间序列csv可视化_Python获取时序数据并进行可视化分析

    本帖最后由 林宝宝 于 2019-7-31 17:29 编辑 问题导读: 1.获取第三方平台的接口数据的方法是什么? 2.怎么做数据清洗与合并?主要有数据类型转换.重新排序.索引重置.数据合并 3.时 ...

  9. python mk趋势检验_时序数据常用趋势检测方法

    背景 在最近的项目中,需要自动检测某段时间内的某个指标是上升了还是下降了,因此需要研究下常用的时序数据趋势检测方法. 方法一 斜率法 原理 斜率法的原理就是使用最小二乘等方法对时序数据进行拟合,然后根 ...

最新文章

  1. matlab“机器学习和深度学习”系列工具箱作用总结
  2. springboot集成themeleaf报Namespace 'th' is not bound
  3. SFTP例子2----使用JSch实现SFTP文件传输
  4. 【实战】tensorflow 花卉识别
  5. PDF搜索、转换与处理类网站
  6. 100. Same Tree 相同的树
  7. php的cookie不存在会是什么值,PHP setcookie() 首次存储不上值
  8. T-SQL编程基础之二:条件选择、循环编程
  9. Android 模拟器中sd卡的创建 和文件的上传
  10. 国外LEAD赚钱教程:EMU篇(五)国外lead常用工具汇总
  11. 阿里云思维导图系列(一)开篇
  12. Squared Error 数学
  13. 比亚迪元EV汽车拆解报告
  14. vue-购物车小球抛物线
  15. python3 Flask 多人答题(完整项目带源码与使用)
  16. Sqlite3安装使用(基于Windows 10)
  17. springboot jar包 一键部署,开机自动启动
  18. C语言中求字符串长度的函数my_strlen()的几种实现方法
  19. android view.measure的用法,自定义View--View的measure过程
  20. linux :ubuntu 安装搜狗输入法

热门文章

  1. Braintree-国外支付对接(一)
  2. 随机信号、严平稳、宽平稳和遍历性随机信号的通俗讲解
  3. php技术外文原文期刊,科学网—选择外文期刊,也是被逼无赖! - 曹建军的博文...
  4. java面向对象 宠物领养系统 包含继承多态的使用 抽象方法和抽象类
  5. 毕业设计-管理系统-俱乐部管理系统
  6. 十大经典排序算法小结(附源码和菜鸟版注释)
  7. 艾美捷 DetergentOUT GB-S10去垢剂的特点和多种应用
  8. json报错:class com.app.model.Document declares multiple JSON fields
  9. Raphael 实现手绘海南省三沙市地图
  10. 如何前端实现微信卡片分享