我需要对一个大熊猫数据框执行非常昂贵的分组操作,并想知道是否有可能先对数据框的前n列进行分组,然后根据我的代码中的条件,重新执行将结果对象分组到另一列上,并因此将新列添加到结果对象的索引中。
当前,DataFrame如下所示:
compound_data = {
'n1': {0: 'n1_value_1', 1: 'n1_value_2', 2: 'n1_value_3'},
'n2': {0: 'n2_value_1', 1: 'n2_value_2', 2: 'n2_value_3'},
'n3': {0: 'n3_value_1', 1: 'n3_value_2', 2: 'n3_value_3'},
'n4': {0: 'n4_value_1', 1: 'n4_value_2', 2: 'n4_value_3'},
}
compound_data_frame = pd.DataFrame(compound_data)
调用groupby的代码块如下所示:
categorical_columns = ['n3', 'n4']
for column in categorical_columns:
counts = compound_data_frame.groupby(
['n1', 'n2', column]).size()
这意味着我最终将n1和n2分组了两次,我担心执行时间会不必要地花费很多。我只想按n1和n2分组一次,然后以某种方式按n3分组第一次分组的结果,然后对n4重复此过程。
因此,如果我要首先对“ n1”和“ n2”列进行分组,则生成的对象可能看起来像这样(我们将此对象称为“ first_grouping”):
n3
index
n1_value/n2_value n3_value
我希望以后可以将其按n3分组并计算结果,以得出以下结果:
count
index
n1_value/n2_value/n3_value 1
之后,我要获取first_grouping对象,但是这次我要按n4而不是n3进行分组,以便最终结果如下所示:
count
index
n1_value/n2_value/n4_value 1
我需要能够访问包含该对象已分组到的所有列的索引,因为这些计数用于更新另一个包含这些操作结果的数据框。第二个数据帧具有如下所示的多重索引:
count
index
n1_value/n2_value/n3_value 1
n1_value/n2_value/n4_value 1
将原始实现与新的,全面的groupby操作一起使用太慢了。
任何帮助将不胜感激。
答案 0 :(得分:1)
IIUC,是的,您可以嵌套groupby
,因为在下面的示例中,apply
中的变量x
是一个数据帧,因此您可以执行相同的操作(例如{ {1}}),就像在任何数据帧上一样:
groupby
尽管在这种情况下,简单的df_ = pd.DataFrame({'n1':list('a'*8), 'n2':list('b'*4+'c'*4),
'n3':list('d'*2+'e'*2)*2, 0:range(8)})
print (df_.groupby(['n1','n2']).apply(lambda x: x.groupby('n3')[[0]].count()))
0
n1 n2 n3
a b d 2
e 2
c d 2
e 2
也会这样做。
编辑:一个更好的示例,该函数根据分组数据帧的大小执行不同的操作:
df_.groupby(['n1','n2','n3'])[[0]].count()
EDIT2:关于问题中的新信息,我认为您可以尝试对n1和n2仅执行def f(x):
gr = x.groupby('n3')[[0]]
return gr.count() if len(x)>=4 else gr.tail(1)
df_ = pd.DataFrame({'n1':list('a'*8), 'n2':list('b'*6+'c'*2),
'n3':list('d'*7+'e'), 0:range(8)})
print (df_.groupby(['n1','n2']).apply(f))
0
n1 n2 n3
a b d 6 #returned the count
c 6 6 #returned the last value of the group
7 7 #...
,然后对categorical_columns的列执行groupby
,value_counts
的结果如下:
concat