我有一个拥有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点而已。
答案 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索引技巧来加快速度。