Pandas DataFrame.apply在计算scipy.stats时速度非常慢

3
我正在尝试创建自定义的DataFrame.describe()函数,该函数将返回以下内容:
  • numpy统计信息
  • scipy统计信息
  • 某些来源的分位数
这应该能够复现我的问题。
# Python 3.6.6, Pandas 0.22.0

import pandas as pd
import numpy as np
import scipy.stats as sc

d = pd.DataFrame(np.random.randint(0,10, size=100000))
d.apply(np.mean) #Works
d.apply(np.std) #Works
d.apply(sc.kurtosis) #Works
d.apply([np.mean, np.std]) #Works
d.apply([np.mean, sc.kurtosis]) # Gets stuck

如果我使用scipy函数,它会无限运行,但如果我只使用numpy,它会非常快速地完成。如果有更好的方法来模拟pd.DataFrame.describe()的输出,并使用自己定制的统计输出列表,我也可以接受。


1
你是指 sc.stats.kurtosis 吗?另外,Pandas 的版本是多少?据我所知,pd.DataFrame.apply 不接受函数列表。 - jpp
是的,我在使用较新版本的pandas,可能这就是为什么它接受列表的原因,我的代码没有错误地运行。我已经更新了以上内容以反映您的修改。 - ackshooairy
当您使用列表理解时,是否发现与我的解决方案相同的问题? - jpp
您的解决方案运行得非常好。现在唯一的问题可能是输出,我可能可以进行配置。我现在看到np.mean返回一个float64,而sc.kurtosis返回一个1个元素数组。我怀疑这与我的方法有关的问题。 - ackshooairy
可能,我怀疑您可以通过检索单元素数组来操纵输出。这并没有回答您关于 apply 的问题,但我们知道 通常情况下,即使在倒数第二个情况下,apply 也很慢。 - jpp
1个回答

1

pd.DataFrame.apply并非神奇。它只是一个Python级别的循环和一个方便的方法。除此之外,它并没有提供太多的便利。它也不接受列表,因为它沿着轴应用单个函数,所以你的代码是错误的。

你可以直接将你的数据框作为参数传递给所有这些函数,并且这展现出了一致的性能:

# Python 3.6.0, Pandas 0.19.2

import pandas as pd
import numpy as np
import scipy as sc

np.random.seed(0)
d = pd.DataFrame(np.random.randint(0,10, size=10**6))

%timeit np.mean(d)                                          # 1.3 ms per loop
%timeit np.std(d)                                           # 2.82 ms per loop
%timeit sc.stats.kurtosis(d)                                # 33 ms per loop
%timeit [func(d) for func in (np.mean, np.std)]             # 3.95 ms per loop
%timeit [func(d) for func in (np.mean, sc.stats.kurtosis)]  # 34.8 ms per loop

1
我认为我可以通过对输出进行一些操作来获得我想要的结果。谢谢。 - ackshooairy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接