时间数据

时间数据

作者: 莫烦 编辑: 莫烦 发布于: 2022-03-13

为什么时间序列在有些数据中十分重要呢? 想想如果你有一批按时间生产的产品,他们的销售业绩和产品质量肯定都绑定在了时间上, 如果哪几天销售好,你也可以回归过来看到底是什么原因导致的,比如节假日,购物节等等。

又或者我有一批数据出现了记录异常,比如我的网站在昨天受黑客攻击了, 我要去定位攻击的时间和影响范围,我肯定要在以时间序列记录的 log 中寻找线索。

所以时间序列不仅仅是数据的一个维度,而且也是协助数据分析的一个重要标尺。

本节要涉及到的功能:

读时间序列数据

我们这里通常说的时间序列是时间点的序列,比如 2022-03-13 12:22:32。看看这些数据是不是常出现在你的报表,或者 log 中? 我们可以用 Pandas 读取文件的方式把这些带着时间序列的数据读出来, 在让 Pandas 识别这些时间序列,你就能对这些时间序列做很多事情。

比如我读出来是这样一份数据。

现在,Pandas 是不知道 time 这个 column 是时间序列的(现在认为它是 object), 我们需要告诉 Pandas 把这个 time 套上时间序列的标识。

你看,现在它就能把这串 object 数据转换成 datetime[64] 了。这就是 Pandas 当中的 Timestamp 数据类型。 就算我的数据不是按标准格式储存的,它也能尝试帮我识别出来标准的日期格式。可见 Pandas 的强悍之处了。

虽然它这么强悍,而且也能识别出非标准准的日期形式,但是输出的结果真的是你期望的吗?万一有个记录员比较有个性, 它喜欢用 月@日@年%%秒|时|分 这种形式记录日期,这么不规范,咋整?

你试试直接解析看看,会出现什么情况?完蛋了,是不是我们就无法接下这个人留下的烂盘了?Pandas 又来拯救你了。 我们如果同时传入一个时间规则 format,有没有可能让 Pandas 按照我们的特殊规则解析?

虽然看起来这串 format 很复杂,但是是可以拆解来看的,他们分别表示的是

  • %m
  • %d
  • %Y 年的全称
  • %% 比配一个 %
  • %S
  • %H
  • %M

规则太多,记不住?没事, Python 有官方文档 可以参考嘛。

自建时间序列

前面我们已经解决了读取到时间序列后,怎么让 Pandas 知道这是时间序列的问题。下面我们如果是要用程序采集数据,比如自己打 log, 或者自己爬虫写日期等等。你要往自己数据库中写日期。介绍一种方式批量生成时间戳。

这种写法就有点像 Python 中的 range() 函数,我们可以规定一个起始日期和终止日期,让 pd.date_range() 自动生成。 那你可能会要问了,range() 里面还有一个 step 参数可以用来控制生成的步长的。 pd.date_range() 也可以吗?

哈哈,想到今年深圳疫情严重,去哪哪都要 48h 的核酸,我也可以做一个打卡表,来看看那些时间点需要去做核酸。只要你想,用 pandas 做一个打卡器也是没问题。 现在你可以在换一下 freq 里面的时间描述,你还可以具体到 1h20min1D 或者是这里 列举的很多 freq 识别的缩写形式。

还有一种在 Numpy 里用的方式 np.linespace(), 这是一种在区间内均匀分割的方法,你也可以用 pd.date_range() 来模拟对日期的分割生成。

pd.date_range() 对于时间个规则性生成还是很友善的。如果你处理工作日比较多,可以参考看看这个 pd.bdate_range() 函数, 它会打开你的眼界。

选取时间

读取完数据,生成完数据,也只是对数据的识别而已, 而现在我们要进入对时间数据的选取阶段,来看怎么选数据的问题。 因为有了这个阶段,我们才能真正开始对时间进行运算

注意,我在生成 Series 的时候,把时间序列挂到了 Seriesindex 上,到时候也可以用这个来作为画图的坐标。

画图出来,就能发现,横坐标已经打上了时间标签。 如果我们不想要一次性展示这么多数据怎么办?如果我们只想要显示某一周时间的数据怎么办?那直接上分片原则吧。

直接用 index 看起来不好弄?不知道到底 index 对应的是哪个日期区间?没关系,我们试试用时间本身分片。

还想继续偷懒,我们直接上日期字符串做索引吧。

甚至,我们还可以按月按年来,真实懒人的福利啊!比如下面我只想看 3 月的数据。

Pandas 的用法可为是真的强大,提供的方式真的很多样!

时间运算

选择时间数据也会了,那我们就来看看如何对时间进行运算吧。这通常发生在需要改变日期数值的时候,比如我想复制一份这周的表格,给下周用, 我就直接将这个月 copy 过来,然后日期上加一周时间。

Timedelta 是一种用于时间加减的时间单位,我们可以个任何一个 Timestamp 加减一个时间。而且 Timedelta 还可以乘除。

Timedelta 除了上面的 weeks, days 参数,还可以用 hours, minutes, seconds, milliseconds, microseconds, nanoseconds 这些。 这样你就能方便的运算时间了。

有时候我都觉得用 Pandas 算日期,比用 Python 原生的 datetime 还要方便。比如下面这些:

用上面的方法,再试试这几个:rng.dayofweek; rng.weekofyear; rng.weekday

用上面的模式,再试试这几个:dt.day_name(); dt.month_name()

当然除了上面的这些方便的转换方法,官方还为我们提供了丰富的转换方式,只要你需要, 你能在这里又发现 Timestamp 转换的一片天地。

时区

如果你的操作系统没配置好,有或者你在其他时区,但有想处理另外的时区。那么学会配置 Pandas 的时区就是一件很重要的事。

默认生成的时候,是不带时区的。所以当你要跨半球工作,你在处理 excel 读取出来的时间,或者你自己要控制时间的时候, 你就要特别标注好时区 tz_localize()

上面我读取到了数据之后,因为老板告诉我这是 New York 时区, 区分于中国时区,我必须先标注是 America/New_York,以防我到时候时间记录错误。 如果要转换到中国时区,我们就可以用下面 tz_convert() 这种方法。

你问我为什么用 Shanghai 不用 Beijing?因为下面用于时区标记中,没有北京。哈哈。

同理,你要获取对应的时区名称,你可以用 pytz 这个库来看。 请参考这里的文档

当你自己要生成一批时间的时候,带上时区的方法就比较简单。直接在 pd.date_range() 里带上 tz 的描述。

总结

不可不说,时间真是一件大工程,围绕时间的处理工作,我也只介绍了冰山一角。还有很多可以在官方文档中查看到, 比如工作日的计算,很多很丰富,但是我觉得你可能很少用,所以就先不介绍了, 有兴趣的朋友可以看看这里的官方文档, 去探索更加全面的时间处理方式吧。


降低知识传递的门槛

莫烦经常从互联网上学习知识,开源分享的人是我学习的榜样。 他们的行为也改变了我对教育的态度: 降低知识传递的门槛免费 奉献我的所学正是受这种态度的影响。 通过 【赞助莫烦】 能让我感到认同,我也更有理由坚持下去。