Pandas时序数据Time Series

深入浅出Pandas读书笔记

C14 Pandas时序数据Time Series

14.1 固定时间

14.1.1 时间的表示

时间戳Timestamp
Pandas是在Python的datetime的基础上建立时间对象的

14.1.2 创建时间点

pd.Timestamp()是Pandas定义时间的主要函数, 代替Python中的datetime.datetime对象

# Timestamp支持的准换语法
pd.Timestamp(datetime.datetime(2020, 6 ,8))
pd.Timestamp('2020-6-8')
pd.Timestamp(2020, 6, 8)
# 支持直接转换timestamp
pd.Timestamp(2000000000, unit='s')
# 支持today, now
pd.Timestamp('now') # 等同 pd.Timestamp.now()
pd.Timestamp('today') # 等同 pd.Timestamp.today()
# 昨天
pd.Timestamp.today() - pd.Timedelta(days=1)
# 替换day为1, 本月的1号
pd.Timestamp.today().replace(day=1)

14.1.3 时间的属性

一个固定的时间包含丰富的属性, 包括时间所在的年份, 月份, 周几, 是否月初, 在哪个季度等

time = pd.Timestamp.now()
time.dayofweek # 周几, 周一为0
time.days_in_month # 本月有多少天 同time.daysinmonth
time.is_leap_year # 是否闰年
time.is_month_end # 是否月末
time.is_month_start # 是否月初
time.is_quarter_end # 当季度最后一天
time.is_quarter_start
time.is_year_end
time.is_year_start
time.quarter
time.week # 当前第几周, 同time.weekofyear
time.day # month, year, second, minute, hour

14.1.4 时间的方法

# 返回星期名
time.day_name # 'Saturday'
time.month_name # 'November'
time.normalize() # 将时间标准化, 去掉时分秒
# 将时间元素替换datetime.replace
time.replace(year=2019)

14.1.5 时间缺失值

pd.Timestamp(pd.NaT)

14.2 时长数据

14.2.1 创建时间差

pd.Timedelta()表示时间差, 也就是时长

pd.Timestamp('2022-12-1') - pd.Timestamp('2022-11-1')
# Timedelta('30 days 00:00:00')
pd.Timedelta(1, unit='d') # Timedelta('1 days 00:00:00')
pd.Timedelta('1 day 2 hour') # Timedelta('1 days 02:00:00')
# 用关键字参数指定时间
pd.Timedelta(days=5, seconds=10)
pd.Timedelta(minutes=3000) # Timedelta('2 days 02:00:00')
# 使用带周期量的偏移量别名
pd.Timedelta('1D') # Timedelta('1 days 00:00:00')
pd.Timedelta('2W') # Timedelta('14 days 00:00:00')
# 带单位的整型数字
pd.Timedelta(1, unit='D')
pd.Timedelta(4, unit='W') # Timedelta('28 days 00:00:00')
# 使用datetime.timedelta
pd.Timedelta(datetime.timedelta(days=1))
# 负值
pd.Timedelta(-1, unit='H') # Timedelta('-1 days +23:00:00')
# 使用时间偏移对象DateOffsets创建
pd.Timedelta(pd.offsets.Minute(2)) # Timedelta('0 days 00:02:00')
pd.Timedelta(pd.offsets.Day(2))
# pd.to_timedelta
pd.to_timedelta(pd.offsets.Day(1)) # Timedelta('1 days 00:00:00') 

14.2.2 时长的加减

# 时长相加减
pd.Timedelta(days=1) + pd.Timedelta(pd.offsets.Hour(5)) # Timedelta('1 days 05:00:00')
pd.Timedelta(days=1) - pd.Timedelta(pd.offsets.Hour(5)) # Timedelta('0 days 19:00:00')
# 固定时间与时长相加减
pd.Timestamp('2020-10-1') + pd.Timedelta(days=10)
pd.Timestamp('2020-10-1') + pd.Timedelta(weeks=3)

14.2.3 时长的属性

tdt = pd.Timedelta(days=10, minutes=9)
tdt.days
tdt.seconds

14.2.4 时长索引

TimedeltaIndex

14.3 时间序列

将众多的固定时间组织起来就形成了时间序列, 即所谓的时序数据. 固定时间在时序数据中可以按照一定的频率组织

14.3.1 时序索引

DatetimeIndex是时间索引对象, 一般由to_datetime()date_range()来创建

pd.to_datetime(['2020-10-1', '2020-11-1']) 
# DatetimeIndex(['2020-10-01', '2020-11-01'], dtype='datetime64[ns]', freq=None)
pd.date_range('2020-10-1', '2020-10-30')
pd.date_range('2020-10-1', periods=30) # 同上
# 
pd.bdate_range('2020-10-1', periods=10) # 跳过周六周日的时间索引序列

14.3.2 创建时序数据

idx = pd.date_range('2020-11-1', periods=10)
s = pd.Series(range(len(idx)), index=idx)
df = pd.DataFrame({'A': range(len(idx)), 'B': range(len(idx))[::-1]}, index=idx)
'''
	A	B
2020-11-01	0	9
2020-11-02	1	8
2020-11-03	2	7
2020-11-04	3	6
2020-11-05	4	5
2020-11-06	5	4
2020-11-07	6	3
2020-11-08	7	2
2020-11-09	8	1
2020-11-10	9	0
'''

14.3.3 数据访问

# 创建2020&2021, 以小时为频率的数据
idx = pd.date_range('2020-1-1', '2021-12-31', freq='H')
ts = pd.Series(np.random.randn(len(idx)), index=idx)
# 指定区间的
ts[5:10]
# 只筛选2020年的
ts['2020'] # ts[2020]是第2020个元素
# 指定天
ts['2020-10-1']
# 如果使用pd.Timestamp 有坑
ts[pd.Timestamp('2020-10-1')] # 这里会查询出Timestamp('2020-10-01 00:00:00')的值
# 查询2021-6月
ts['2020-6']
# 2021 6-10月
ts['2021-6':'2021-10']
# 时间粒度
ts.index.resolution # hour
# df.truncate() 返回一个新的对象, 避免直接赋值修改原数据
ts.truncate(before='2020-11-10', after='2020-12-1')

14.3.4 类型转换

s = pd.Series(['2020-10-1', '2020-12-1'])
s.astype('datetime64')
# pd.to_datetime转换
pd.to_datetime(s)
# pd.to_datetime()还可以将多列组合成一个时间进行转换
df = pd.DataFrame({'year': [2020, 2021, 2022],
                   'month': [10, 11, 12],
                   'day': [10, 11, 12]
                  })
pd.to_datetime(df.loc[:, :])
'''
0   2020-10-10
1   2021-11-11
2   2022-12-12
dtype: datetime64[ns]
'''

14.3.5 按格式转换

如果时间格式不规范, 指定转换格式

pd.to_datetime('2020-12-11', format='%Y-%d-%m', errors='ignore')
pd.to_datetime(200000000, unit='s') # 转换时间戳
# 将列表转换为时间
pd.to_datetime([10, 11, 12, 13], unit='D', origin='2020-10-1')
# DatetimeIndex(['2020-10-11', '2020-10-12', '2020-10-13', '2020-10-14'], dtype='datetime64[ns]', freq=None)

14.3.6 时间访问器.dt

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

s = pd.Series(pd.date_range('2020-1-1', periods=5))
s.dt.day_name() # 各天是星期几
s.dt.time
s.dt.year # month, day, hour, minute, second, microsecond, nanosecond
# 与周, 月, 年相关的属性
s.dt.week # 等同于, 将被Series.dt.isocalendar().week替代
s.dt.dayofweek # s.dt.weekday, 一周中的周几
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.normalize() # 去掉时分秒
s.dt.month_name() # January
s.dt.day_name() # Wednesday

s.dt.strftime('%F')

14.3.7 时长数据访问器

ts = pd.Series(pd.to_timedelta(np.arange(5), unit='H'))
ts.dt.seconds

14.3.8 时序数据移动 shift()

14.3.9 频率转换 asfreq()

将时间序列由一个频率单位更换为另一个频率单位, 实现时间颗粒度的变化.

rng = pd.date_range('2020-11-1', '2020-12-1')
ts = pd.Series(range(len(rng)), index=rng)
# 将它的频率变为更细的粒度, 会产生缺失值, 用0填充缺失值
ts.asfreq(pd.offsets.Hour(12), fill_value=0) 
# 用指定方法填充
ts.asfreq(pd.offsets.Hour(12), method='ffill') 

14.4 时间偏移 DataOffset

DateOffset 与 Timedelta的区别
DateOffset使用日历中日期的规则, 而不是进行事件性质的算数计算
Timedelata是一个时长间隔

14.4.1 DateOffset对象

t = pd.Timestamp('2020-10-1')
t + pd.Timedelta(days=1)
t + pd.DateOffset(days=1) # 结果同上
# 加2个工作日
d = pd.Timestamp('2020-10-30')
d.day_name() # 'Friday'
new_day = d + pd.offsets.BDay(2)
new_day # Timestamp('2020-11-03 00:00:00')
new_day.day_name() # 'Tuesday'

与时长Timedelta不同, 时间偏移DateOffset不是数学意义上的增加或减少, 而是根据实际生活的日历对现有时间进行偏移

14.4.2 偏移别名

14.4.3 移动偏移

14.4.4 应用偏移

14.4.5 偏移参数

import datetime
d = datetime.datetime(2020, 6, 1, 9, 0)
d_new = d + pd.offsets.Waek(1, weekday=4, normalize=True) # 可以指定偏移一周, 偏移到周中的周四
# 当年年末
d + pd.offsets.YearEnd(normalize=True)
# 当年某月月末
d + pd.offsets.YearEnd(month=6, normalize=True)

14.4.6 相关查询

当使用日期作为索引的DataFrame时, 此函数可以基于日期偏移量选择

i = pd.date_range('2020-10-1', periods=4, freq='2D')
ts = pd.DataFrame({'A': [1, 2, 3, 4]}, index=i)
# 取时间序列上最后的3天
ts.last('3D') # 前3天 ts.first('3D')
'''
A
2020-10-05	3
2020-10-07	4
'''
# 取最后3行
ts.tail(3)
'''
	A
2020-10-03	2
2020-10-05	3
2020-10-07	4
'''

14.4.7 与时序的计算

可以对Series或DatetimeIndex时间索引列应用时间偏移

rng = pd.date_range('2020-1-1', '2020-1-3')
s = pd.Series(rng)
s + pd.DateOffset(months=2)
s - pd.DateOffset(months=2)
s - pd.DateOffset(days=2)

14.4.8 锚定偏移

14.4.9 自定义工作时间

14.5 时间段

14.5.1 Period对象

我们用pd.Period()创建时间段对象

14.5.2 属性方法

14.5.3 时间段计算

14.5.4 时间段索引

14.5.5 数据查询

14.5.6 相关类型转换

14.6 时间操作

14.6.1 市区转换

14.6.2 时间的格式化

# 解析时间格式
pd.to_datetime('2020-11-13', format='%Y-%m-%d')
# Timestamp('2020-11-13 00:00:00')
pd.Timestamp.now().strftime('%F') # '2022-11-20'

14.6.3 时间重采样

Pandas可以对时序数据按不同的频率进行重采样操作, resample()可以按照5分钟, 15分钟, 半小时等频率进行分组, 然后完成聚合计算.

idx = pd.date_range('2020-1-1', periods=500, freq='min')
ts = pd.Series(range(len(idx)), index=idx)
# 按5分钟重采样
ts.resample('5MIN').sum()
ts.resample('5MIN').mean()
ts.resample('5MIN').max()

14.6.4 上采样 upsampling

上采样upsampling一般应用在图像学中, 目的是放大图像. 由于原数据有限, 放大图像后需要对缺失值进行内插值填充.

14.6.5 重采样聚合

14.6.6 时间类型转换

14.6.7 超出时间戳范围时间

14.6.8 区间间隔

你可能感兴趣的:(深入浅出Pandas,pandas,python,数据分析)