让 Pandas 与 Pendulum 一起工作

Posted

技术标签:

【中文标题】让 Pandas 与 Pendulum 一起工作【英文标题】:Making Pandas work with Pendulum 【发布时间】:2018-05-30 16:00:52 【问题描述】:

我最近偶然发现了一个新的很棒的pendulum library,可以更轻松地处理日期时间。

pandas 中,有这个方便的to_datetime() method 允许将系列和其他对象转换为日期时间:

raw_data['Mycol'] = pd.to_datetime(raw_data['Mycol'], format='%d%b%Y:%H:%M:%S.%f')

创建自定义 to_<something> 方法的规范方法是什么 - 在这种情况下,to_pendulum() 方法可以将日期字符串系列直接转换为Pendulum objects?

这可能导致Series 具有各种有趣的功能,例如,将一系列日期字符串转换为一系列"offsets from now" - human datetime diffs。

【问题讨论】:

嗯,你有什么想法?您可以继承 Series 对象,其中您可以添加一个 to_pendulum 方法来执行您想要的操作。 Here's 子类化系列官方指南。 @cᴏʟᴅsᴘᴇᴇᴅ 我最初只是想调用 apply() 方法,但后来我对 pandas 的了解非常有限,不确定创建这样的自定义转换方法的最合适方法.会阅读指南,谢谢! 啊,好吧。好像我误会了。所以,你有一列日期时间,你想应用这个钟摆 diff_for_humans 函数? (对不起,我不熟悉这个库)。如果就这么简单,您可以只定义一个函数并将其传递给pd.Series.apply,子类化一个系列就有点过头了。 @cᴏʟᴅsᴘᴇᴇᴅ 没问题,我不够清楚。我最初想将一列(系列)日期时间字符串转换为一列 Pendulum 对象,以便以后能够更轻松地进行日期时间操作 - 人工日期时间差异、时区转换和 pendulum 提供的其他方便的东西。 【参考方案1】:

创建自定义to_<something> 的规范方法是什么? 方法 - 在这种情况下 to_pendulum() 方法将能够 将 Series 日期字符串直接转换为 Pendulum 对象?

稍微浏览了 API 之后,我必须说我对他们所做的事情印象深刻。不幸的是,我不认为 Pendulumpandas 可以一起工作(至少,与当前的最新版本 - v0.21)。

最重要的原因是pandas 本身并不支持Pendulum 作为数据类型。所有原生支持的数据类型(np.intnp.floatnp.datetime64)都以某种形式支持矢量化。使用数据框(例如,香草循环和列表),您不会获得一丝性能改进。如果有的话,使用Pendulum 对象在Series 上调用apply 将会更慢(因为所有API 开销)。

另一个原因是Pendulumdatetime的子类——

from datetime import datetime

isinstance(pendulum.now(), datetime)
True

这很重要,因为如上所述,datetime 是受支持的数据类型,因此 pandas 将尝试datetime 强制转换为 pandas 的本机日期时间格式 - Timestamp。这是一个例子。

print(s)

0     2017-11-09 18:43:45
1     2017-11-09 20:15:27
2     2017-11-09 22:29:00
3     2017-11-09 23:42:34
4     2017-11-10 00:09:40
5     2017-11-10 00:23:14
6     2017-11-10 03:32:17
7     2017-11-10 10:59:24
8     2017-11-10 11:12:59
9     2017-11-10 13:49:09

s = s.apply(pendulum.parse)
s

0    2017-11-09 18:43:45+00:00
1    2017-11-09 20:15:27+00:00
2    2017-11-09 22:29:00+00:00
3    2017-11-09 23:42:34+00:00
4    2017-11-10 00:09:40+00:00
5    2017-11-10 00:23:14+00:00
6    2017-11-10 03:32:17+00:00
7    2017-11-10 10:59:24+00:00
8    2017-11-10 11:12:59+00:00
9    2017-11-10 13:49:09+00:00
Name: timestamp, dtype: datetime64[ns, <TimezoneInfo [UTC, GMT, +00:00:00, STD]>]

s[0]
Timestamp('2017-11-09 18:43:45+0000', tz='<TimezoneInfo [UTC, GMT, +00:00:00, STD]>')

type(s[0])
pandas._libs.tslib.Timestamp

因此,您可以通过一些困难(涉及dtype=object)将Pendulum 对象加载到数据帧中。以下是你的做法 -

v = np.vectorize(pendulum.parse)
s = pd.Series(v(s), dtype=object)

s

0     2017-11-09T18:43:45+00:00
1     2017-11-09T20:15:27+00:00
2     2017-11-09T22:29:00+00:00
3     2017-11-09T23:42:34+00:00
4     2017-11-10T00:09:40+00:00
5     2017-11-10T00:23:14+00:00
6     2017-11-10T03:32:17+00:00
7     2017-11-10T10:59:24+00:00
8     2017-11-10T11:12:59+00:00
9     2017-11-10T13:49:09+00:00

s[0]
<Pendulum [2017-11-09T18:43:45+00:00]>

然而,这基本上是没用的,因为调用 any pendulum 方法(通过apply)现在不仅会超级慢,而且最终会导致结果被强制为@再次987654348@,徒劳无功。

【讨论】:

对于未来的读者...Github issue on making pandas with pendulum: github.com/pandas-dev/pandas/issues/15986

以上是关于让 Pandas 与 Pendulum 一起工作的主要内容,如果未能解决你的问题,请参考以下文章

我如何让 pandas 使用 spark 集群

Pandas数据处理二

如何将 PreferenceFragment 与 ViewPager 一起使用?

如何将 pandas.style 与 streamlit 一起使用

text pendulum.help

将 PANDAS 与 Apache Beam 一起使用