Pandas 10-时序数据

Pandas 10-时序数据

import numpy as np
import pandas as pd

一、时序中的基本对象

时间序列的概念在日常生活中十分常见,但对于一个具体的时序事件而言,可以从多个时间对象的角度来描述。例如2020年9月7日周一早上8点整需要到教室上课,这个课会在当天早上10点结束,其中包含了哪些时间概念?

  • 第一,会出现时间戳(Date times)的概念,即’2020-9-7 08:00:00’和’2020-9-7 10:00:00’这两个时间点分别代表了上课和下课的时刻,在pandas中称为Timestamp。同时,一系列的时间戳可以组成DatetimeIndex,而将它放到Series中后,Series的类型就变为了datetime64[ns],如果有涉及时区则为datetime64[ns, tz],其中tz是timezone的简写。

  • 第二,会出现时间差(Time deltas)的概念,即上课需要的时间,两个Timestamp做差就得到了时间差,pandas中利用Timedelta来表示。类似的,一系列的时间差就组成了TimedeltaIndex, 而将它放到Series中后,Series的类型就变为了timedelta64[ns]

  • 第三,会出现时间段(Time spans)的概念,即在8点到10点这个区间都会持续地在上课,在pandas利用Period来表示。类似的,一系列的时间段就组成了PeriodIndex, 而将它放到Series中后,Series的类型就变为了Period

  • 第四,会出现日期偏置(Date offsets)的概念,假设你只知道9月的第一个周一早上8点要去上课,但不知道具体的日期,那么就需要一个类型来处理此类需求。再例如,想要知道2020年9月7日后的第30个工作日是哪一天,那么时间差就解决不了你的问题,从而pandas中的DateOffset就出现了。同时,pandas中没有为一列时间偏置专门设计存储类型,理由也很简单,因为需求比较奇怪,一般来说我们只需要对一批时间特征做一个统一的特殊日期偏置。

通过这个简单的例子,就能够容易地总结出官方文档中的这个表格

概念 单元素类型 数组类型 pandas数据类型
Date times Timestamp DatetimeIndex datetime64[ns]
Time deltas Timedelta TimedeltaIndex timedelta64[ns]
Time spans Period PeriodIndex period[freq]
Date offsets DateOffset None None

由于时间段对象Period/PeriodIndex的使用频率并不高,因此将不进行讲解,而只涉及时间戳序列、时间差序列和日期偏置的相关内容。

二、时间戳

1. Timestamp的构造与属性

单个时间戳的生成利用pd.Timestamp实现,一般而言的常见日期格式都能被成功地转换:

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

通过year, month, day, hour, minute, second可以获取具体的数值:

ts.year
2021
ts.month
1
ts.day
1
ts.hour
8
ts.minute
10
ts.second
30

pandas中,时间戳的最小精度为纳秒ns,由于使用了64位存储,可以表示的时间范围大约可以如下计算:
T i m e   R a n g e = 2 64 1 0 9 × 60 × 60 × 24 × 365 ≈ 585 ( Y e a r s ) \rm Time\,Range = \frac{2^{64}}{10^9\times 60\times 60\times 24\times 365} \approx 585 (Years) TimeRange=109×60×60×24×365264585(Years)
通过pd.Timestamp.maxpd.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序列的生成

一组时间戳可以组成时间序列,可以用to_datetimedate_range来生成。其中,to_datetime能够把一列时间戳格式的对象转换成为datetime64[ns]类型的时间序列:

pd.to_datetime(['2021-1-1', '2021/1/3', '20210106'])
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(['2021\\1\\1','2021\\1\\3'],format='%Y\\%m\\%d')
temp
DatetimeIndex(['2021-01-01', '2021-01-03'], dtype='datetime64[ns]', freq=None)

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

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

另外,还存在一种把表的多列时间属性拼接转为时间序列的to_datetime操作,此时的列名必须和以下给定的时间关键词列名一致:

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

date_range是一种生成连续间隔时间的一种方法,其重要的参数为start, end, freq, periods,它们分别表示开始时间,结束时间,时间间隔,时间戳个数。其中,四个中的三个参数决定了,那么剩下的一个就随之确定了。这里要注意,开始或结束日期如果作为端点则它会被包含:

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

这里的freq参数与DateOffset对象紧密相关,将在第四节介绍其具体的用法。

【练一练】

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

My solution :

  • 定义一个函数 , 设置三个参数 , start代表输入的起始日期 , end代表输入的终止日期 , length代表需要生成多长的日期系列(含首尾)
  • 分别将输入的startend转换为pd.Timestamp类型
  • lenth不大于2不做讨论 , 默认lenth大于2
  • sample生成length-2个随机数 , 乘以period加上start换算为指定区间的随机数 , 拼接startend并转换为无符号64位整数 , 再转成日期序列
def random_datetime(start,end,length):
    start, end = pd.Timestamp(start), pd.Timestamp(end)
    return pd.to_datetime([start.value,*np.uint64((end.value-start.value)*np.random.sample(length-2)+start.value),end.value])
  • 传入起始和终止日期 , 生成一个长度为10的随机日期序列 , 并排序
random_datetime('20210101',
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值