熊猫分组依据

时间:2019-08-29 22:23:22

标签: python-3.x pandas pandas-groupby

我试图基于某个键在两个数据帧上进行成对比较,但是我在pandas groupby的double for循环中遇到了困难,因为它非常慢。有什么我可以优化的方法,这样我每次运行外循环时都不必重新计算组?

我尝试使用相同的groupby变量,但似乎无法解决重新计算问题。

mygroups = mydf.groupby('mykey')
for key1,subdf1 in mygroups:
    for key2,subdf2 in mygroups:
        if(key2 <= key1):
            continue
        do_some_work(subdf1,subdf2)

subdf2似乎从第一个键而不是从key1之后的下一个键开始重新计算。在我的用例场景中,我期望key2将是迭代中key1之后的下一个,依此类推。无需重新计算如何发生这种行为?

1 个答案:

答案 0 :(得分:1)

您的观察是正确的,内部循环遍历整个数据帧,而不仅仅是key1之后的记录。

用于较小的DataFrame的最简单方法

我先创建一个包含组的列表,然后遍历该列表。 这就是我要做的:

mygroups_list= [(key, subdf) for (key, subdf) mydf.groupby('mykey')]

for len(mygroups_list) > 0:
    key1,subdf1= mygroups_list.pop(0)
    for key2,subdf2 in mygroups_list:
        do_some_work(subdf1,subdf2)

您只需要确保对组进行了真正的排序,但是AFAIK仍然可以通过.groupby方法来完成。如果不确定,可以在循环外添加一个mygroups_list.sort(key=lambda tup: tup[0])

如果大小还很重要

对于较大的数据框,您可以避免立即实例化这些数据框,而只需将其推迟到您实际需要这样的数据时即可:

# create the groupby object as usual
group_by= mydf.groupby('mykey')

# now fetch the row indices from the groupby object
# and because this is actually a dictionary
# extract the keys from it and sort them
mygroups_dict= group_by.indices
mygroups_labels= list(mygroups_dict)
mygroups_labels.sort()

# now use a similar approach as above
while len(mygroups_labels) > 0:
    key1= mygroups_labels.pop(0)
    # but instead of creating the sub dataframes
    # before you enter the loop, just do it
    # within the loop and use the row indices
    # the groupby object evaluated
    subdf1= mydf.iloc[mygroups_dict[key1]]
    for key2 in mygroups_labels:
        subdf2= mydf.iloc[mygroups_dict[key2]]
        do_some_work(subdf1, subdf2)

这应该减少大量的内存,因为您只需要存储行索引,而不是在整个孔处理时间内存储整个行。

对于以下示例设置:

import numpy as np
def do_some_work(subdf1, subdf2):
    print('{} --> {} (len={}/{})'.format(subdf1['mykey'].iat[0], subdf2['mykey'].iat[0], len(subdf1), len(subdf2)))

mydf= pd.DataFrame(dict(mykey=np.random.randint(5, size=100), col=range(1, 101)))

这将输出类似(当然,由于randint,len信息在每次运行时看起来都将有所不同)。但是请注意组标签(箭头的左右)。在右侧,您会一直看到key2,它始终是> key1:

0 --> 1 (len=21/16)
0 --> 2 (len=21/21)
0 --> 3 (len=21/20)
0 --> 4 (len=21/22)
1 --> 2 (len=16/21)
1 --> 3 (len=16/20)
1 --> 4 (len=16/22)
2 --> 3 (len=21/20)
2 --> 4 (len=21/22)
3 --> 4 (len=20/22)