如何成为一个快速的熊猫与groupbys

时间:2015-03-09 16:24:55

标签: python performance pandas bigdata dataframe

我有一个拥有1.5亿行的Pandas数据帧。其中有大约100万个小组,我想做一些非常简单的计算。例如,我想采用一些现有的专栏'A'并制作一个新专栏'A_Percentile',该专栏在组内表达“A'的百分位数等级值”。这是一个小功能:

from scipy.stats import percentileofscore

def rankify(column_name,data=my_data_frame):
    f = lambda x: [percentileofscore(x, y) for y in x]
    data[column_name+'_Percentile'] = data.groupby(['Group_variable_1',
                                               'Group_variable_2'])[column_name].transform(f)
    return

然后你可以这样称呼它:

rankify('Column_to_Rank', my_data_frame)

等待......很长一段时间。

我可以采取一些明显的措施来加快速度(例如,我确信有一种方法可以对[percentileofscore(x, y) for y in x]进行矢量化)。但是,我觉得有一些熊猫的技巧可以帮我加快速度。我可以用groupby逻辑做些什么吗?我想把它分开并将其并行化,但是1.我不确定这是一个好方法.2。写出数据和读取结果的通信时间似乎需要几乎相同的时间(或许我认为因为第1点而已。

1 个答案:

答案 0 :(得分:2)

您可能已经意识到,groupby操作的速度可能会有很大差异 - 尤其是当组数量增加时。这是一个非常简单的替代方法,在我尝试的一些测试数据集上速度要快得多(速度提高2倍到40倍)。通常,如果您可以避免用户编写的函数(与groupby结合使用)并坚持使用内置函数(通常是cython化),它会更快:

In [163]: %timeit rankify('x',df)
1 loops, best of 3: 7.38 s per loop

In [164]: def rankify2(column_name,data):
     ...:     r1 = data.groupby('grp')[column_name].rank()
     ...:     r2 = data.groupby('grp')[column_name].transform('count')
     ...:     data[column_name+'_Percentile2'] = 100. * r1 / r2 

In [165]: %timeit rankify2('x',df)
10 loops, best of 3: 178 ms per loop

请注意,与10e-15相比,我的方法得出的结果略有不同(例如percentileofscore()的差异)。因此,如果您使用x == y测试结果,则大多数将为True,但有些将为False,但x.round() == y.round()将通过。

对于上面的结果,这是我的测试数据集(对于我尝试的其他情况,差异较小,但总是2倍或更好的加速):

df = pd.DataFrame( { "grp" : np.repeat( np.arange(1000), 100 ),
                     "x"   : np.random.randn(100000)           } )

如果你愿意的话,我相信你可以做得更好。真的,你需要做的就是排序和排名。我怀疑我采取的基本方法是一个很好的方法,但如果你在numpy或numba中做了部分或全部,你可以加快速度。此外,您可以使用一些pandas索引技巧来加快速度。