问题 让Pandas与Pendulum合作


我最近偶然发现了一个令人敬畏的新东西 pendulum 图书馆 使用日期时间更轻松。

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

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

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

这可能会导致 Series 具有各种有趣的功能,例如,将一系列日期字符串转换为一系列日期字符串 “从现在起抵消” - 人类日期时间的差异


7809
2017-12-16 19:42


起源

嗯,你有什么想法?你可以继承 Series 对象,您可以在其中添加 to_pendulum 做你想要的方法。 - coldspeed
这里的 子类化系列的官方指南。 - coldspeed
@cᴏʟᴅsᴘᴇᴇᴅ我最初想的只是打电话给 apply() 方法,但是我对熊猫的知识非常有限,并且不确定创建这样的自定义转换方法的最合适的方法。请阅读指南,谢谢! - alecxe
啊,好吧。好像我误解了。那么,你有一列日期时间,你想应用这个摆锤diff_for_humans函数? (对不起,我对这个图书馆不熟悉)。如果它就这么简单,你可以定义一个函数并将其传递给 pd.Series.apply,继承系列只会是矫枉过正。 - coldspeed
@cᴏʟᴅsᴘᴇᴇᴅ没问题,我不够清楚。我想最初将日期时间字符串的列(系列)转换为Pendulum对象列,以便稍后能够使日期时间操作更容易 - 人类日期时间差异,时区转换和钟摆提供的其他方便的事情。 - alecxe


答案:


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

在仔细研究了API之后,我必须说我对他们所做的事情印象深刻。不幸的是,我不认为 Pendulum 和 pandas 可以一起工作(至少,与目前的最新版本 - v0.21)。

最重要的原因是 pandas 本来不支持 Pendulum 作为数据类型。所有本机支持的数据类型(np.intnp.float 和 np.datetime64)以某种形式支持矢量化。使用数据帧,例如,一个vanilla循环和列表,你不会得到一丝性能提升。如果有的话,打电话 apply 在...上 Series  同 Pendulum 对象将是 比较慢 (因为所有的API开销)。

另一个原因是 Pendulum 是。的子类 datetime  -

from datetime import datetime

isinstance(pendulum.now(), datetime)
True

这很重要,因为如上所述, datetime 是一种受支持的数据类型,所以pandas会 尝试 强迫 datetime 到熊猫的原生日期时间格式 - 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]>

然而,这基本上是没用的,因为打电话 任何  pendulum 方法(通过 apply)现在不仅会超级慢,而且最终会被强迫结果 Timestamp 再次,徒劳无功。


14
2017-12-16 20:17