【python数据分析(18)】Pandas中时间序列处理(4)pd.to_period()与pd.to_timestamp()数据之间转换以及时间序列索引及切片
1. period时期数据
1.1 pd.Period()
创建时期数据
1) pd.Period()
参数:一个时间戳 + freq
参数 → freq
用于指明该 period
的长度,时间戳则说明该 period
在时间轴上的位置
import pandas as pd
p = pd.Period('2020', freq = 'M')
print(p)
print(type(p))
–> 输出的结果为:(输出的结果为2020年的第一个月份的日期数据)
2020-01
<class 'pandas._libs.tslibs.period.Period'>
2) 可以通过加减运算进行(年、月)日期数据的变换
print(p + 1)
print(p - 2)
print(pd.Period('2020', freq = 'A-DEC') - 1)
–> 输出的结果为:
2020-02
2019-11
2019
1.2 pd.period_range()
创建时期范围
1) 简单demo
prng = pd.period_range('1/1/2020', '1/1/2021', freq='M')
print(prng)
print(type(prng))
print(prng[0])
print(type(prng[0]))
–> 输出的结果为:
PeriodIndex(['2020-01', '2020-02', '2020-03', '2020-04', '2020-05', '2020-06',
'2020-07', '2020-08', '2020-09', '2020-10', '2020-11', '2020-12',
'2021-01'],
dtype='period[M]', freq='M')
<class 'pandas.core.indexes.period.PeriodIndex'>
2020-01
<class 'pandas._libs.tslibs.period.Period'>
★★★★★2) 如果将生成的时间索引转化为我们日常中见到的字符串数据的话,如下
print([str(prng[i]) for i in range(len(prng))])
month_day = list(zip(prng.month,prng.day))
print(month_day)
–> 输出的结果为:(可以对比上一篇的将时间戳索引转化为字符串数据的方式,如果也是用这种方式会怎么样)
['2020-01', '2020-02', '2020-03', '2020-04', '2020-05', '2020-06', '2020-07', '2020-08', '2020-09', '2020-10', '2020-11', '2020-12', '2021-01']
[(1, 31), (2, 29), (3, 31), (4, 30), (5, 31), (6, 30), (7, 31), (8, 31), (9, 30), (10, 31), (11, 30), (12, 31), (1, 31)]
★★★★★ 3) 对比一下上一个博客中关于时间戳索引转化为字符串数据
data = pd.date_range('2020','2021', freq = 'M')
print([str(data[i]) for i in range(len(data))])
–> 输出的结果为:(通过两者的对比,就可以更清楚的了解什么是时间戳索引和日期索引,上面输出月和天就是为了和下面的输出做对比)
['2020-01-31 00:00:00', '2020-02-29 00:00:00', '2020-03-31 00:00:00', '2020-04-30 00:00:00', '2020-05-31 00:00:00', '2020-06-30 00:00:00', '2020-07-31 00:00:00', '2020-08-31 00:00:00', '2020-09-30 00:00:00', '2020-10-31 00:00:00', '2020-11-30 00:00:00', '2020-12-31 00:00:00']
4) 创建时期数据的TimeSeries
时间序列
ts = pd.Series(np.random.rand(len(prng)), index = prng)
print(ts,type(ts))
print(ts.index)
–> 输出的结果为:(标签为时期数据,后面是数值的Series,和之前的时刻数据类似,一个是时刻数据,一个是时间段)
2020-01 0.733202
2020-02 0.330304
2020-03 0.079378
2020-04 0.836970
2020-05 0.540214
2020-06 0.423610
2020-07 0.944636
2020-08 0.617366
2020-09 0.223554
2020-10 0.057547
2020-11 0.567743
2020-12 0.121468
2021-01 0.196632
Freq: M, dtype: float64 <class 'pandas.core.series.Series'>
PeriodIndex(['2020-01', '2020-02', '2020-03', '2020-04', '2020-05', '2020-06',
'2020-07', '2020-08', '2020-09', '2020-10', '2020-11', '2020-12',
'2021-01'],
dtype='period[M]', freq='M')
1.3 频率转换
在numpy中进行数据类型的转换,使用到了astype()
的方法,而在pandas里面要进行时间频率的转换有点类似,是通过.asfreq(freq, method=None, how=None)
方法转换成别的频率
p = pd.Period('2020','A-DEC')
print(p)
print(p.asfreq('M', how = 'start')) # 也可写 how = 's'
print(p.asfreq('D', how = 'end')) # 也可写 how = 'e'
–> 输出的结果为:
2020
2020-01
2020-12-31
★★★★★ 将时期索引(时期对应的时间序列)转化为时刻索引(时刻对应的时间序列)
prng = pd.period_range('2020','2021',freq = 'M')
ts1 = pd.Series(np.random.rand(len(prng)), index = prng)
ts2 = pd.Series(np.random.rand(len(prng)), index = prng.asfreq('D', how = 'start'))
print(ts1.head())
print(type(ts1.index))
print(ts2.head())
print(type(ts2.index))
–> 输出的结果为:(注意这里转换频率后,数据类型是不变的,并不是真正变成了时刻数据,仍然还是时期数据,只是形式上和之前的时刻索引一致)
2020-01 0.017181
2020-02 0.193328
2020-03 0.047001
2020-04 0.043000
2020-05 0.295609
Freq: M, dtype: float64
<class 'pandas.core.indexes.period.PeriodIndex'>
2020-01-01 0.801138
2020-02-01 0.654645
2020-03-01 0.185378
2020-04-01 0.357173
2020-05-01 0.122337
Freq: D, dtype: float64
<class 'pandas.core.indexes.period.PeriodIndex'>
1.4 时刻与时期数据之间的转换
上面的示例可以发现并没有实现真正上的时刻(时间戳)数据与时期数据之间的转换,那么接下来就是实现真正意义上的数据类型的转换,使用的方法是:pd.to_period()
、pd.to_timestamp()
1) 时刻转时期
rng = pd.date_range('2020/1/1', periods = 10, freq = 'M')
ts1 = pd.Series(np.random.rand(len(rng)), index = rng)
ts2 = ts1.to_period()
print(ts1.head())
print(type(ts1.index))
print(ts2.head())
print(type(ts2.index))
–> 输出的结果为:(实现时刻数据向时期数据的转化)
2020-01-31 0.181266
2020-02-29 0.934712
2020-03-31 0.179842
2020-04-30 0.372101
2020-05-31 0.799920
Freq: M, dtype: float64
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
2020-01 0.181266
2020-02 0.934712
2020-03 0.179842
2020-04 0.372101
2020-05 0.799920
Freq: M, dtype: float64
<class 'pandas.core.indexes.period.PeriodIndex'>
2) 时期转时刻
prng = pd.period_range('2020','2021', freq = 'M')
ts3 = pd.Series(np.random.rand(len(prng)), index = prng)
ts4 = ts3.to_timestamp()
print(ts3.head())
print(type(ts3.index))
print(ts4.head())
print(type(ts4.index))
–> 输出的结果为:(实现时期数据向时刻数据的转化)
2020-01 0.287591
2020-02 0.056996
2020-03 0.566121
2020-04 0.725879
2020-05 0.067077
Freq: M, dtype: float64
<class 'pandas.core.indexes.period.PeriodIndex'>
2020-01-01 0.287591
2020-02-01 0.056996
2020-03-01 0.566121
2020-04-01 0.725879
2020-05-01 0.067077
Freq: MS, dtype: float64
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
2. 时间序列 - 索引及切片
TimeSeries
是Series
的一个子类,所以Series
索引及数据选取方面的方法基本一样;同时TimeSeries
通过时间序列有更便捷的方法做索引和切片;时间序列由于按照时间先后排序,故不用考虑顺序问题
1)简单索引
from datetime import datetime
rng = pd.date_range('2020/1','2020/3')
ts = pd.Series(np.random.rand(len(rng)), index = rng)
print(ts.head())
print(ts[0])
–> 输出的结果为:
2020-01-01 0.402184
2020-01-02 0.435946
2020-01-03 0.524105
2020-01-04 0.605212
2020-01-05 0.852766
Freq: D, dtype: float64
0.40218382128573316
2) 时间序列标签索引,支持各种时间字符串,以及datetime.datetime
print(ts['2020/1/2'])
print(ts['20200103'])
print(ts['1/10/2020'])
print(ts[datetime(2020,1,20)])
–> 输出的结果为:(可以实现多种日期字符串形式的索引)
0.6968196406360381
0.3747735841244546
0.3420296886910025
0.11972763328609326
3) 切片
★★★★★ 关于第三种方式的切片特别实用,比如调用某一个月的数据,进行查看或者处理
rng = pd.date_range('2020/1','2020/3',freq = '12H')
ts = pd.Series(np.random.rand(len(rng)), index = rng)
print(ts[:2])
print(ts['2020/1/5':'2020/1/10'])
print(ts['2020/2'].head())
–> 输出的结果为:(三个不同方式的切片,第一个直接按照行数切片,第二个按照索引切片,第三个直接传入月份进行切片)
2020-01-01 00:00:00 0.182351
2020-01-01 12:00:00 0.203575
Freq: 12H, dtype: float64
2020-01-05 00:00:00 0.805461
2020-01-05 12:00:00 0.728251
2020-01-06 00:00:00 0.065754
2020-01-06 12:00:00 0.606569
2020-01-07 00:00:00 0.801891
2020-01-07 12:00:00 0.995801
2020-01-08 00:00:00 0.056166
2020-01-08 12:00:00 0.110309
2020-01-09 00:00:00 0.195206
2020-01-09 12:00:00 0.984065
2020-01-10 00:00:00 0.464639
2020-01-10 12:00:00 0.574147
Freq: 12H, dtype: float64
2020-02-01 00:00:00 0.804735
2020-02-01 12:00:00 0.134206
2020-02-02 00:00:00 0.088963
2020-02-02 12:00:00 0.368319
2020-02-03 00:00:00 0.602443
Freq: 12H, dtype: float64
4) 重复索引的时间序列
有时候,日期数据里面并不止一个时间标签,结果就是一个标签对应多个数据,检查标签和数值是否重复的方式为:is_unique
dates = pd.DatetimeIndex(['1/1/2020','1/2/2020','1/3/2020','1/4/2020','1/1/2020','1/2/2020'])
ts = pd.Series(np.random.rand(6), index = dates)
print(ts)
print(ts.is_unique,ts.index.is_unique)
–> 输出的结果为:
2020-01-01 0.650634
2020-01-02 0.272747
2020-01-03 0.627082
2020-01-04 0.182520
2020-01-01 0.455632
2020-01-02 0.869520
dtype: float64
True False
index
有重复的索引时候将返回多个值
print(ts['20200101'],type(ts['20200101']))
print(ts['20200104'],type(ts['20200104']))
–> 输出的结果为:
2020-01-01 0.650634
2020-01-01 0.455632
dtype: float64 <class 'pandas.core.series.Series'>
2020-01-04 0.18252
dtype: float64 <class 'pandas.core.series.Series'>
如果要处理同一标签对应的数据,可以在分组的时候添加level = 0
这个参数,也就是在标签数据进行唯一值处理(按照标签值进行分组)
print(ts.groupby(level = 0).mean())
–> 输出的结果为:(这里选择的处理方式为,按照平均值处理)
2020-01-01 0.553133
2020-01-02 0.571133
2020-01-03 0.627082
2020-01-04 0.182520
dtype: float64
上一篇: php下汉字转化为拼音的代码_php技巧
下一篇: 理解pipenv in Python