赞
踩
目录
时间序列
是指多个时间点上形成的数值序列,它既可以是定期的,也可以是不定期出现的。
时间序列的数据主要有以下几种:
时间戳:timestamp:表示特定的某个时刻,比如现在。
时期:period:比如2022年或者2022年3月。
时间间隔:interval:由起始时间戳和结束时间戳表示。
在Pandas中,最基本的时间序列类型就是以时间戳
为索引的Series对象
。
时间戳使用Timestamp(Series派生的子类)对象表示,该对象与datetime具有高度的兼容性,可以直接通过to_datetime()
函数将datetime
转换为TimeStamp
对象。
例如:
- import pandas as pd
- from datetime import datetime
- import numpy as np
-
- print(pd.to_datetime('20200828142123')) # 将datetime转换为Timestamp对象,年月日 时秒分
当传入的是多个datetime组成的列表,则Pandas会将其强制转换为DatetimeIndex类对象。
- # 传入多个datetime字符串
- date_index = pd.to_datetime(['20200820151423', '20200828212325', '20200908152360'])
- print(date_index)
- 按照索引获取时间戳:
-
- for i in range(len(date_index)):
- print(date_index[i])
pandas时间戳为索引的Series对象
- # 创建时间序列类型的Series对象
- date_index = pd.to_datetime(['20200820151423', '20200828212325', '20200908152360'])
- # 创建以时间戳为索引的series对象
- date_ser = pd.Series([11, 22, 33], index=date_index)
- print(date_ser)
也可将包含多个datetime对象的列表传给index参数,同样能创建具有时间戳索引的Series对象。
- # 指定索引为多个datetime的列表
- date_list = [datetime(2020, 1, 1), datetime(2020, 1, 15),
- datetime(2020, 2, 20), datetime(2020, 4, 1),
- datetime(2020, 5, 5), datetime(2020, 6, 1)]
- time_se = pd.Series(np.arange(6), index=date_list)
- print(time_se)
DataFrame对象具有时间戳索引
- data_demo = [[11, 22, 33], [44, 55, 66],
- [77, 88, 99], [12, 23, 34]]
- date_list = [datetime(2020, 1, 23), datetime(2020, 2, 15),
- datetime(2020, 5, 22), datetime(2020, 3, 30)]
- time_df = pd.DataFrame(data_demo, index=date_list)
- print(time_df)
- # 指定索引为多个日期字符串的列表,要有相同的格式
- date_list = ['2017.05.30', '2019.02.01',
- '2017.6.1', '2018.4.1',
- '2019.6.1', '2020.1.23']
- # 将日期字符串转换为DatetimeIndex
- date_index = pd.to_datetime(date_list)
- # 创建以DatetimeIndex 为索引的Series对象
- date_se = pd.Series(np.arange(6), index=date_index)
- print(date_se)
选取子集:
1、通过位置索引获取子集数据
print(date_se[3])
2、使用datetime构造的日期获取数据
- #根据datetime构造日期获取
- date_time = datetime(2018,4,1)
- print(date_se[date_time])
3、通过符合格式要求的日期字符串获取
- #传入相应的符合日期的字符串获取
- print(date_se['20180401'])
- print(date_se['2018.04.01'])
- print(date_se['2018/04/01'])
- print(date_se['2018-04-01'])
- print(date_se['04/01/2018'])
4、直接用指定的年份或者月份操作索引来获取某年的数据
print(date_se['2017'])
5、使用过truncate()方法截取 Series或DataFrame对象
truncate(before = None,after = None,axis = None,copy = True)
before – 表示截断此索引值之前的所有行。
after – 表示截断此索引值之后的所有行。
axis – 表示截断的轴,默认为行索引方向。
- # 扔掉2018-1-1之前的数据
- sorted_se = date_se.sort_index()
- print(sorted_se.truncate(before='2018-1-1'))
-
- # 扔掉2018-7-31之后的数据
- print(sorted_se.truncate(after='2018-7-31'))
Pandas中所提供的date_range()函数,主要用于生成一个具有固定频率的DatetimeIndex对象。
参数说明:
start:表示起始日期,默认为None。
end:表示终止日期,默认为None。
periods:表示产生多少个时间戳索引值。
freq:用来指定计时单位。
注意:
start
、end
、periods
、freq
这四个参数至少要指定三个参数,否则会出现错误。
用法如下:
1.当调用date_range()函数创建DatetimeIndex对象时,如果只是传入了开始日期(start参数)与结束日期(end参数),则默认生成的时间戳是按天计算的,即freq参数为D
- # 创建DatetimeIndex对象时,只传入开始日期与结束日期
- print(pd.date_range('2020/08/10', '2023/08/20'))
2.若只是传入了开始日期或结束日期,则还需要用periods参数指定产生多少个时间戳。
- # 创建DatetimeIndex对象时,传入start与periods参数
- print(pd.date_range(start='2020/08/10', periods=5))
-
- # 创建DatetimeIndex对象时,传入end与periods参数,往前推
- print(pd.date_range(end='2020/08/10', periods=5))
3.如果希望时间序列中的时间戳都是每周固定的星期日,则可以在创建DatetimeIndex时将freq参数设为“W-SUN”。
- dates_index = pd.date_range('2020-01-01', # 起始日期
- periods=5, # 周期
- freq='W-SUN') # 频率
- print(dates_index)
4.如果日期中带有与时间相关的信息,且想产生一组被规范化到当天午夜的时间戳,可以将normalize参数的值设为True。
- # 创建DatetimeIndex,并指定开始日期、产生日期个数、默认的频率,以及时区
- date_index = pd.date_range(start='2020/8/1 12:13:30', periods=5,
- tz='Asia/Hong_Kong')
- print(date_index)
-
- #规范化时间戳
- date_index2 = pd.date_range(start='2020/8/1 12:13:30', periods=5,
- normalize=True, tz='Asia/Hong_Kong')
- print(date_index2)
1.默认生成的时间序列数据是按天计算的,即频率为“D”。
“D”是一个基础频率,通过用一个字符串的别名表示,比如“D”是“day”的别名。
频率是由一个基础频率和一个乘数组成的,比如,“5D”表示每5天。
其他频率说明如下:
用于指定freq属性:
- date_time5D = pd.date_range(start='2020/2/1', end='2020/2/28', freq='5D')
- print(date_time5D)
2.每个基础频率还可以跟着一个被称为日期偏移量的DateOffset对象。如果想要创建一个DateOffset对象,则需要先导入pd.tseries.offsets模块后才行。
可以指定偏移量创建时间序列,同时,创建14天10小时的偏移量,可以换算为两周零十个小时,其中“周”使用Week类型表示的,“小时”使用Hour类型表示,它们之间可以使用加号连接。
- import pandas as pd
- from datetime import datetime
- import numpy as np
- from pandas.tseries.offsets import *
-
- date_offset1 = DateOffset(weekday=2,hour=10)
- ''' - year
- - month
- - day
- - weekday
- - hour
- - minute
- - second
- - microsecond
- - nanosecond.'''
- date_offset2 = Week(2) + Hour(10)
-
- date_index1 = pd.date_range('2020/3/1',periods=5,freq=date_offset1)
- date_index2 = pd.date_range('2020/3/1',periods=5,freq=date_offset2)
- print(date_index1)
- print(date_index2)
移动是指沿着时间轴方向将数据进行前移或后移。如下图所示:
Pandas对象中提供了一个shift()方法,用来前移或后移数据,但数据索引保持不变。
用法如下:
- shift(periods=1, freq=None, axis=0)
- #periods – 表示移动的幅度,可以为正数,也可以为负数,默认值是1,代表移动一次。
- date_index = pd.date_range('2020/01/01', periods=5)
- time_ser = pd.Series(np.arange(5) + 1, index=date_index)
- print(time_ser)
- # 向后移动一次
- print(time_ser.shift(1))
- #向前移动一次
- print(time_ser.shift(-1))
1.Period类表示一个标准的时间段或时期,比如某年、某月、某日、某小时等。
创建Period类对象的方式比较简单,只需要在构造方法中以字符串或整数的形式传入一个日期即可。
- # 创建Period对象,表示从2020-01-01到2020-12-31之间的时间段
- period = pd.Period(2020)
- print(period)
-
- # 表示从2019-06-01到2019-06-30之间的整月时间
- period = pd.Period('2019/6')
- print(period)
2.Period对象能够参与数学运算。
如果Period对象加上或者减去一个整数,则会根据具体的时间单位进行位移操作。
- period = period + 1 # Period对象加上一个整数
- print(period)
如果具有相同频率的两个Period对象进行数学运算,那么计算结果为它们的单位数量。
- # 表示从2019-06-01到2019-06-30之间的整月时间
- period = pd.Period('2019/6')
- print(period)
-
- period = period + 1 # Period对象加上一个整数
- print(period)
-
- # 创建一个与period频率相同的时期
- other_period = pd.Period(201401, freq='M' )
- print(period - other_period)
3.如果希望创建多个Period对象,且它们是固定出现的,则可以通过period_range()函数实现。
返回一个PeriodIndex对象,它是由一组时期对象构成的索引,示例如下:
- period_index = pd.period_range('2014.1.8', '2014.5.31', freq='M')
- print(period_index)
4.除了使用上述方式创建PeriodIndex外,还可以直接在PeriodIndex的构造方法中传入一组日期字符串。
- period_index = pd.period_range('2014.1.8', '2014.5.31', freq='M')
- print(period_index)
-
- str_list = ['2012', '2013', '2014']
- period_list = pd.PeriodIndex(str_list, freq='A-DEC')
- print(period_list)
- time_index = pd.Series(np.arange(len(period_index)) + 1,index = period_index)
- print(time_index)
注意:DatetimeIndex是用来指代一系列时间点的一种索引结构,而PeriodIndex则是用来指代一系列时间段的索引结构。
1.Pandas中提供了一个asfreq()方法来转换时期的频率。
asfreq(freq,method = None,how = None,normalize = False,fill_value = None )
参数说明:
freq – 表示计时单位。
how – 可以取值为start或end,默认为end。
normalize – 表示是否将时间索引重置为午夜。
fill_value – 用于填充缺失值的值。
- # 创建时期对象
- period = pd.Period('2019', freq='A-DEC')
- print(period)
- period_freq_start = period.asfreq('M', how='start')
- print(period_freq_start)
- period_freq_end = period.asfreq('M',how='end')
- print(period_freq_end)
1.Pandas中的resample()是一个对常规时间序列数据重新采样和频率转换的便捷的方法。
resample(rule, how=None, axis=0, fill_method=N
- date_index = pd.date_range('2019.7.8', periods=30)
- time_ser = pd.Series(np.arange(len(date_index)) + 1, index=date_index)
- print(time_ser)
-
- print(time_ser.resample('W-MON').mean())
one, closed=None, label=None, ...)
参数说明:
rule – 表示重采样频率的字符串或DateOffset。
fill_method – 表示升采样时如何插值。
closed – 设置降采样哪一端是闭合的。
1.通过resample()方法对数据重新采样
注意:how参数不再建议使用,而是采用新的方式“.resample(…).mean()”求平均值。
2.如果重采样时传入closed参数为left,则表示采样的范围是左闭右开型的。
即位于某范围的时间序列中,开头的时间戳包含在内,结尾的时间戳是不包含在内的。
print(time_ser.resample('W-MON', closed='left').mean())
1.降采样时间颗粒会变大,数据量是减少的。为了避免有些时间戳对应的数据闲置,可以利用内置方法聚合数据。
例如股票数据比较常见的是OHLC重采样,包括开盘价、最高价、最低价和收盘价。
Pandas中专门提供了一个ohlc()方法。
- date_index = pd.date_range('2020/06/01', periods=30)
- shares_data = np.random.rand(30)
- time_ser = pd.Series(shares_data, index=date_index)
- print(time_ser)
- result = time_ser.resample('7D').ohlc() # OHLC重采样 得到七天中的开盘价,最高价,最低价以及收盘价
- print(result)
2.降采样相当于另外一种形式的分组操作,它会按照日期将时间序列进行分组,之后对每个分组应用聚合方法得出一个结果。
- # 通过groupby技术实现降采样
- result = time_ser.groupby(lambda x: x.week).mean()
- print(result)
1.升采样的时间颗粒是变小的,数据量会增多,这很有可能导致某些时间戳没有相应的数据。
遇到这种情况,常用的解决办法就是插值,具体有如下几种方式:
通过ffill(limit)或bfill(limit)方法,取空值前面或后面的值填充,limit可以限制填充的个数。
通过fillna(‘ffill’)或fillna(‘bfill’)进行填充,传入ffill则表示用NaN前面的值填充,传入bfill则表示用后面的值填充。
通过使用interpolate()方法根据插值算法补全数据。
- data_demo = np.array([['101', '210', '150'], ['330', '460', '580']])
- date_index = pd.date_range('2020/06/10', periods=len(data_demo), freq='W-SUN')
- time_df = pd.DataFrame(data_demo, index=date_index,
- columns=['A产品', 'B产品', 'C产品'])
- print(time_df)
-
- #增加采样时间,但没有填充数据
- time_df_asfreq = time_df.resample('D').asfreq()
- print(time_df_asfreq)
-
- #用前面的数据填充
- time_df_ffill = time_df.resample('D').ffill()
- print(time_df_ffill)
-
- #用后面的数据 填充
- time_df_bfill = time_df.resample('D').bfill()
- print(time_df_bfill)
1.滑动窗口指的是根据指定的单位长度来框住时间序列,从而计算框内的统计指标。
相当于一个长度指定的滑块在刻度尺上面滑动,每滑动一个单位即可反馈滑块内的数据。
示例如下:
某分店按天统计了2017年全年的销售数据,现在总经理想抽查分店8月28日(七夕)的销售情况,如果只是单独拎出来当天的数据,则这个数据比较绝对,无法很好地反映出这个日期前后销售的整体情况。
为了提升数据的准确性,可以将某个点的取值扩大到包含这个点的一段区间,用区间内的数据进行判断。
可以将8月24日到9月2日的数据拿出来,求此区间的平均值作为抽查结果。
这个区间就是窗口,它的单位长度为10,数据是按天统计的,所以统计的是10天的平均指标,这样显得更加合理,可以很好地反映了七夕活动的整体情况。
3.移动窗口就是窗口向一端滑行,每次滑行并不是区间整块的滑行,而是一个单位一个单位的滑行。
例如,窗口向右边滑行一个单位,此时窗口框住的时间区间范围为2017-08-25到2017-09-03。
每次窗口移动,一次只会移动一个单位的长度,并且窗口的长度始终为10个单位长度,直至移动到末端。
由此可知,通过滑动窗口统计的指标会更加平稳一些,数据上下浮动的范围会比较小。
Pandas中提供了一个窗口方法rolling()。
rolling(window, min_periods=None, center=False, win_type=None, on=None, axis=0, closed=None)
参数说明:
window – 表示窗口的大小。
min_periods – 每个窗口最少包含的观测值数量。
center – 是否把窗口的标签设置为居中。
win_type – 表示窗口的类型。
closed – 用于定义区间的开闭。
- year_data = np.random.randn(365)
- date_index = pd.date_range('2017-01-01', '2017-12-31', freq='D')
- ser = pd.Series(year_data, date_index)
- print(ser.head()) #打印前几个数据 默认为5
-
- #画图观察
- import matplotlib.pyplot as plt
-
- ser.plot(style='y--')
- ser_window = ser.rolling(window=10).mean()
- ser_window.plot(style='b')
- plt.show()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。