gpt4 book ai didi

python - groupby 的 last 在 pandas 中的性能问题

转载 作者:太空狗 更新时间:2023-10-30 00:07:14 24 4
gpt4 key购买 nike

我有一个包含两列和超过十万个元素的 DataFrame。

In [43]: df.head(10)
Out[43]:
localtime ref
4 2014-04-02 12:00:00.273537 139058754703810577
5 2014-04-02 12:00:02.223501 139058754703810576
6 2014-04-02 12:00:03.518817 139058754703810576
7 2014-04-02 12:00:03.572082 139058754703810576
8 2014-04-02 12:00:03.572444 139058754703810576
9 2014-04-02 12:00:03.572571 139058754703810576
10 2014-04-02 12:00:03.573320 139058754703810576
11 2014-04-02 12:00:09.278517 139058754703810576
14 2014-04-02 12:00:20.942802 139058754703810577
15 2014-04-02 12:01:13.410607 139058754703810576

[10 rows x 2 columns]

In [44]: df.dtypes
Out[44]:
localtime datetime64[ns]
ref int64
dtype: object

In [45]: len(df)
Out[45]: 111743

In [46]: g = df.groupby('ref')

如果我从我的组中请求最后一个元素,函数就会挂起!

In [47]: %timeit g.last()

我在 6 分钟后杀死了它; top 显示 CPU 始终处于 100%。

如果我明确请求 localtime 列,这至少会返回,尽管它看起来仍然慢得离谱,因为元素很少。

In [48]: %timeit g['localtime'].last()
1 loops, best of 3: 4.6 s per loop

有什么我想念的吗?这是 Pandas 0.13.1。


此问题出现在 datetime64 类型中。假设我直接从文件中读取:

In [1]: import pandas as pd

In [2]: df = pd.read_csv('so.csv')

In [3]: df.dtypes
Out[3]:
localtime object
ref int64
dtype: object

In [4]: %timeit df.groupby('ref').last()
10 loops, best of 3: 28.1 ms per loop

object 类型工作得很好。但是,如果我投下我的时间戳,一切都会崩溃:

In [5]: df.localtime = pd.to_datetime(df.localtime)

In [6]: df.dtypes
Out[6]:
localtime datetime64[ns]
ref int64
dtype: object

In [7]: %timeit df.groupby('ref').last()

情节变厚了。


在没有数据文件的情况下复制,使用 Jeff 的建议:

In [70]: rng = pd.date_range('20130101',periods=20,freq='s')

In [71]: df = pd.DataFrame(dict(timestamp = rng.take(np.random.randint(0,20,size=100000)), value = np.random.randint(0,100,size=100000)*1000000))

In [72]: %timeit df.groupby('value').last()
1 loops, best of 3: 332 ms per loop

但是,如果我改变随机整数的范围,那么问题又出现了!

In [73]: df = pd.DataFrame(dict(timestamp = rng.take(np.random.randint(0,20,size=100000)), value = np.random.randint(0,100000,size=100000)*1000))

In [74]: %timeit df.groupby('value').last()

我只是简单地增加了第二个randint()high参数,这意味着groupby()会有更大的长度。这在没有数据文件的情况下重现了我的错误。

请注意,如果我放弃 datetime64 类型,则没有问题:

In [12]: df = pd.DataFrame(dict(timestamp = np.random.randint(0,20,size=100000), value = np.random.randint(0,100000,size=100000)*1000))

In [13]: %timeit df.groupby('value').last()
100 loops, best of 3: 14.4 ms per loop

所以罪魁祸首是在 datetime64 上缩放 last()

最佳答案

一定是发生了什么奇怪的事情……在 0.13.1(和主版本)中看起来不错。发布指向您的文件的链接,我会看一看。

In [3]: rng = date_range('20130101',periods=20,freq='s')

In [4]: df = DataFrame(dict(timestamp = rng.take(np.random.randint(0,20,size=100000)), value = np.random.randint(0,100,size=100000)*1000000))

In [5]: df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 100000 entries, 0 to 99999
Data columns (total 2 columns):
timestamp 100000 non-null datetime64[ns]
value 100000 non-null int64
dtypes: datetime64[ns](1), int64(1)
In [6]: %timeit df.groupby('value')['timestamp'].last()
100 loops, best of 3: 9.07 ms per loop

In [7]: %timeit df.groupby('value')['timestamp'].tail(1)
100 loops, best of 3: 16.3 ms per loop

好的,这是解释:

使用 np.random.randint(0,100,size=100000) 作为值,创建 100 个组,而 np.random.randint(0,100000,size=100000) 创造了更多(在我的示例中63000) 左右。

.last(在 <0.14 中)隐式执行最后一个 non-nan 值。这个 na 测试并不便宜,所以它的扩展性能很差(并且是在每个组的 python 空间中完成的)。

tail(1) 另一方面(在 < 0.14 中)不对此进行检查,因此性能要好得多(并使用 cython 路由来获取结果)。

在 0.14 中,这些将是相同的(即使你这样做:nth(-1,dropna='any') 这将复制last在这里做,这是以一种有更好性能的方式完成的。(感谢@Andy Hayden)。

底线是在 <0.14 中使用 tail(1)

关于python - groupby 的 last 在 pandas 中的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22845856/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com