Pandas数据分析22——pandas时间序列

 参考书目:《深入浅出Pandas:利用Python进行数据处理与分析》


pandas的索引可以用时间来替代,然后基于时间序列数据会有很多用法,了解一下。

时间对象有:

还是先导入包:

import numpy as np 
import pandas as pd 
import datetime

时序索引

#创建时间索引

pd里面的对象,或者字符串,np对象,和Python的datetime对象都可以直接创建时间索引。

pd.to_datetime(['11/1/2020',np.datetime64('2020-11-02'),datetime.datetime(2020,11,3)])

 date_range创建一组时间,即时间序列

#默认频率为天
pd.date_range('2020-01-01',periods=10)
pd.date_range('2020-01-01','2020-01-10') #同上
pd.date_range(end='2020-01-10',periods=10)#同上
pd.date_range('2022-01-01', periods=3, freq='H')#频率为小时

 #跳过星期六天

pd.bdate_range('2020-11-1',periods=10)

 #通常时间序列数据作为 Series 或 DataFrame 的索引,以方便对时间数据进行操作。

# 指定开始时间和频率,周期数
pd.Series(range(3), index=pd.date_range('2000', freq='D', periods=3))


索引访问

和其他种类数据一样,时间序列也是可以用[],.loc[]方法进行切片选取数据的。

生成案例数据

rng = pd.date_range('1/1/2021', '12/1/2021', freq='BM')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts

#时间索引切片 

#DatetimeIndex 作为时间索引,同样也支持数据切片:
ts[2:4]

ts[0:4].index  #ts[::2].index

#还支持传入时间字符和各种时间对象 

ts['2021'] #z只筛选2021年的
ts['1/29/2021']#查询这一天的值
ts['2021-1-29']#同上
ts['20210129'] #同上

ts[datetime.datetime(2021, 9, 30):]
ts[pd.Timestamp(2021,9,30)]
ts[pd.Timestamp('2021-9-30')]
ts[np.datetime64('2021-9-30')]

 #也可以使用部分字符查询一定范围的数据:

ts['2021'] # 查询整个2021年的
ts['2021-6'] # 查询 2021年6月的
ts['2021-6':'2021-10'] # 6月到10月的
dft['2013-1':'2013-2-28 00:00:00'] # 精确时间
dft['2013-1-15':'2013-1-15 12:30:00']
dft2.loc['2013-01-05']

类型转化


#由于时间格式样式比较多,很多情况下 Padnas 并不能自动识别为时间类型,所以我们在处理前的数据清洗过程中,需要专门对数据进行时间类型转换。
#astype 是最简单的时间转换方法,它只能针对相对标准的时间格式,如:

s = pd.Series(['2016-01-31', '2016-02-29', '2016-03-31'])
s.astype('datetime64[ns]')

#修改频率

s.astype('datetime64[D]')

pd.to_datetime(s)


#转为不同时间粒度

#在上文中,我们转换时间时使用的是 ns (纳秒),最大程度地保留了最细的时间颗粒的供我们未来使用,但有时间我们不需要这么精确的细小粒度,如何操作呢?这就需要在 datetime64 后的括号里指定我们想要的粒度,如:

# 一个时间文本序列
s = pd.Series(['2016-01-31 10:18:04', '2016-02-29 12:18:09'])
s
'''
0    2016-01-31 10:18:04
1    2016-02-29 12:18:09
dtype: object
'''
# 纳秒级
s.astype('datetime64[ns]')
'''
0   2016-01-31 10:18:04
1   2016-02-29 12:18:09
dtype: datetime64[ns]
'''
# 日级
s.astype('datetime64[D]')
'''
0   2016-01-31
1   2016-02-29
dtype: datetime64[ns]
'''
# 小时级
s.astype('datetime64[h]')
'''
0   2016-01-31 10:00:00
1   2016-02-29 12:00:00
dtype: datetime64[ns]
'''
# 秒级
s.astype('datetime64[s]')
'''
0   2016-01-31 10:18:04
1   2016-02-29 12:18:09
dtype: datetime64[ns]
'''
# 月级,当月第一天
s.astype('datetime64[M]')
'''
0   2016-01-01
1   2016-02-01
dtype: datetime64[ns]
'''
# 年级,当年第一天
s.astype('datetime64[Y]')
'''
0   2016-01-01
1   2016-01-01
dtype: datetime64[ns]
'''
# 周级,当周周四(原因如下)
s.astype('datetime64[W]')
'''
0   2016-01-28
1   2016-02-25
dtype: datetime64[ns]
'''

'datetime64[W]' 的结果为周四是因为这只是四舍五入,是经过设计的。括号里还可以为 2W、7D等开工,如 7D 的意思是“自纪元(1970-01-01T00:00Z )以来7D的倍数”,就像 D 的意思是“自纪元以来一天的倍数”,7D 和 W 是同义词。

我们可以看到,除了周、月、年等,其他粒度仍然以纳秒存储,不过精确度都会损失。这个规划在下边我们介绍的 pd.to_datetime() 中也适用。


转为时间 pd.to_datetime

#Pandas 提供的 pd.to_datetime() 是识别转换时间的主要工具。接下来看一些例子。

#从 DataFrame 的多个列中组合一个日期时间。 键可以是常见的缩写,例如['year','month','day','minute','second','ms','us','ns']): 必须: year, month, day 可选: hour, minute, second, millisecond, microsecond, nanosecond

df = pd.DataFrame({'year': [2015, 2016],
                   'month': [2, 3],
                   'day': [4, 5]})
df

pd.to_datetime(df)
pd.to_datetime(df[['year', 'month', 'day']]) # 同上

 #对Series智能解析时间:

pd.to_datetime(pd.Series(['Jul 31, 2009', '2010-01-10', None]))

 #列表也可以智能

pd.to_datetime(['2005/11/23', '2010.12.31'])
# DatetimeIndex(['2005-11-23', '2010-12-31'], dtype='datetime64[ns]', freq=None)

pd.to_datetime(['04-01-2012 10:00'], dayfirst=True) # 日期在前
# DatetimeIndex(['2012-01-04 10:00:00'], dtype='datetime64[ns]', freq=None)
#pd.DatetimeIndex 也可以转换:
pd.DatetimeIndex(['2018-01-01', '2018-01-03', '2018-01-05'])
# DatetimeIndex(['2018-01-01', '2018-01-03', '2018-01-05'], dtype='datetime64[ns]', freq=None)

pd.DatetimeIndex(['20180101', '20180103', '20180105'], freq='infer') #自动推断频率
# DatetimeIndex(['2018-01-01', '2018-01-03', '2018-01-05'], dtype='datetime64[ns

 #可以使用 pd.Timestamp() 进行转换单个时间点

pd.to_datetime('2010/11/12')
# Timestamp('2010-11-12 00:00:00')

pd.Timestamp('2020/11/12')
# Timestamp('2020-11-12 00:00:00')

按格式转换

#不规则格式转化时间

pd.to_datetime('2020_11_12',format='%Y_%m_%d',errors='ignore')

 

pd.to_datetime('20200101', format='%Y%m%d', errors='ignore')

# 可以让系统自己推断时间格式

pd.to_datetime('20200101', infer_datetime_format=True, errors='ignore')

# coerce 将不会忽略错误,返回空值
pd.to_datetime('13000101', format='%Y%m%d', errors='coerce')

# 有时间需要字段转为字符,再转为时间

pd.to_datetime(df.d.astype(str), format='%m/%d/%Y')

# 其他
pd.to_datetime('2010/11/12', format='%Y/%m/%d')
# Timestamp('2010-11-12 00:00:00')

pd.to_datetime('12-11-2010 00:00', format='%d-%m-%Y %H:%M')
# Timestamp('2010-11-12 00:00:00')

#对时间戳进行转换,需要给出时间单位,一般为秒:
pd.to_datetime(1490195805, unit='s')
# Timestamp('2017-03-22 15:16:45')
pd.to_datetime(1490195805433502912, unit='ns')
# Timestamp('2017-03-22 15:16:45.433502912')

#对周期数据(数字列表)进行转换:
pd.to_datetime([1, 2, 3], unit='D',origin=pd.Timestamp('1960-01-01'))
# DatetimeIndex(['1960-01-02', '1960-01-03', '1960-01-04'], dtype='datetime64[ns]', fre

.dt 时间访问器

#对于时间序列数据,可以使用 s.dt.xxx 的形式来访问它们的属性和调用它们的方法

s = pd.Series(pd.date_range('2020-01-01', periods=3, freq='d'))
s.dt.date
s.dt.time
s.dt.timetz
s.dt.year
s.dt.month
s.dt.day
s.dt.hour
s.dt.minute
s.dt.second
s.dt.microsecond
s.dt.nanosecond

#周月年相关
s.dt.week
s.dt.weekofyear
s.dt.dayofweek
s.dt.weekday
s.dt.dayofyear      #一年中第几天
s.dt.quarter        #季度数
s.dt.is_month_start #是否月第一天
s.dt.is_month_end   #是否最后一天
s.dt.is_quarter_start#是否季度第一天
s.dt.is_quarter_end #是否季度最后一天
s.dt.is_year_start  #是否年第一天
s.dt.is_year_end    #是否年最后一天
s.dt.is_leap_year   #是否闰年
s.dt.daysinmonth    #当月多少天
s.dt.days_in_month  #同上
s.dt.tz     #时区
s.dt.freq   #频率

#转化方法
s.dt.to_period
s.dt.to_pydatetime
s.dt.tz_localize
s.dt.tz_convert
s.dt.normalize
s.dt.strftime

s.dt.round(fred='D')#类似四舍五入
s.dt.floor(fred='D')#向下舍入为天
s.dt.ceil(fred='D') #向上舍入为天

s.dt.month_name     #月份名称
s.dt.day_name       #星期几名称
s.dt.qyear
s.dt.start_time     #开始时间
s.dt.end_time       #结束时间
s.dt.days           #天数
s.dt.seconds        #秒
s.dt.microseconds   #毫秒
s.dt.nanoseconds    #纳秒
s.dt.components     #时间成分
s.dt.to_pytimedelta #转为py时间
s.dt.total_seconds  #总秒数

移动 Shifting

 #可能需要将时间序列中的值在时间上前后移动或滞后。 shift() 方法也可以在时序对象上使用。

index = pd.date_range('2020-06-01', '2020-06-03')
ts = pd.Series(range(len(rng)), index=index)
ts

ts.shift(-1)

ts.shift(-1,freq='B')


频率转换 asfreq()

有时候需要将低频率数据改为高频数据

#更改频率的主要功能是 asfreq() 方法。
dr = pd.date_range('1/1/2022', periods=3, freq=3 * pd.offsets.BDay())
ts = pd.Series(np.random.randn(3), index=dr)
ts

日期频率

ts.asfreq(pd.offsets.BDay())

 半天频率

ts.asfreq(pd.offsets.Hour(12))

 #asfreq 提供了更多便利,因此您可以为频率转换后可能出现的任何间隙指定插值方法。

ts.asfreq(pd.offsets.BDay(), method='pad')  #扩展填充

# 对空值进行固定值填充
ts.asfreq(freq='12h', fill_value=9.0)


扩充日期,填充

#以使用几个选项之一({None, ‘backfill’/’bfill’, ‘pad’/’ffill’, ‘nearest’})来填写缺失值。
#例如,要反向传播最后一个有效值以填充NaN值,请将 bfill 作为参数传递给method关键字。

ts.reindex(pd.date_range('2022-1-1', periods=15, freq='D'), method='ffill')

 可以看到有效的将三个数据扩充到更多的额时间天上,并且值填充保持不变。

猜你喜欢

转载自blog.csdn.net/weixin_46277779/article/details/126269587
今日推荐