如何在 pandas 中进行这种聚合?
How can I make this kind of aggregation in pandas?
我有一个包含分类列和数字列的数据框,我想根据分类列的值对数字列(最大、最小、总和...)的值进行一些聚合(所以我有为每个分类列可以采用的每个值创建新列)。
为了更好理解table,最好放个玩具例子
说我有这个数据框:
import pandas as pd
df = pd.DataFrame({
'ref' : [1, 1, 1, 2, 2, 3],
'value_type' : ['A', 'B', 'A', 'C', 'C', 'A'],
'amount' : [100, 50, 20, 300, 150, 70]
}).set_index(['ref'])
value_type amount
ref
1 A 100
1 B 50
1 A 20
2 C 300
2 C 150
3 A 70
我想根据 value_type 的值对金额进行分组,也针对每个参考进行分组。这种情况下的结果(假设只需要求和)将是这个:
df_result = pd.DataFrame({
'ref' : [1, 2, 3],
'sum_amount_A' : [120, 0, 70],
'sum_amount_B' : [50, 0, 0],
'sum_amount_C' : [0, 450, 0]
}).set_index('ref')
sum_amount_A sum_amount_B sum_amount_C
ref
1 120 50 0
2 0 0 450
3 70 0 0
我试过一些可行的方法,但效率极低。大约需要几分钟来处理 30.000 行。
我所做的是这样的:(我有一个数据框,每个索引引用只有一行,称为 df_final)
df_grouped = df.groupby(['ref'])
for ref in df_grouped.groups:
df_aux = df.loc[[ref]]
column = 'A' # I have more columns, but for illustration one is enough
for value in df_aux[column].unique():
df_aux_column_value = df_aux.loc[df_aux[column] == value]
df_final.at[ref,'sum_' + column + '_' + str(value)] = np.sum(df_aux_columna_valor[column])
我相信应该有更好的方法来进行这种聚合...提前致谢!!
编辑:
当只有一列作为分组依据时,给出的答案是正确的。在真实的数据框中,我有几列我想计算一些聚合函数,但分别计算每列的值。我的意思是我不想要列值的每个组合的聚合值,而只是列本身的聚合值。
举个例子
import pandas as pd
df = pd.DataFrame({
'ref' : [1, 1, 1, 2, 2, 3],
'sexo' : ['Hombre', 'Hombre', 'Hombre', 'Mujer', 'Mujer', 'Hombre'],
'lugar_trabajo' : ['Campo', 'Ciudad', 'Campo', 'Ciudad', 'Ciudad', 'Campo'],
'dificultad' : ['Alta', 'Media', 'Alta', 'Media', 'Baja', 'Alta'],
'amount' : [100, 50, 20, 300, 150, 70]
}).set_index(['ref'])
这个数据框看起来像这样:
sexo lugar_trabajo dificultad amount
ref
1 Hombre Campo Alta 100
1 Hombre Ciudad Media 50
1 Hombre Campo Alta 20
2 Mujer Ciudad Media 300
2 Mujer Ciudad Baja 150
3 Hombre Campo Alta 70
如果我按几列分组,或者做一个主元table(据我所知,这在某种程度上是等价的),这样做:
df.pivot_table(index='ref',columns=['sexo','lugar_trabajo','dificultad'],values='amount',aggfunc=[np.sum,np.min,np.max,len], dropna=False)
我将得到一个包含 48 列的数据框(因为我有 3 * 2 * 2 个不同的值和 4 个聚合函数)。
实现我想要的结果的一种方法是:
df_agregado = pd.DataFrame(df.index).set_index('ref')
for col in ['sexo','lugar_trabajo','dificultad']:
df_agregado = pd.concat([df_agregado, df.pivot_table(index='ref',columns=[col],values='amount',aggfunc=[np.sum,np.min,np.max,len])],axis=1)
我一个人做每一组,然后把它们全部拼接起来。通过这种方式,我得到 28 列(2 * 4 + 3 * 4 + 2 * 4)。它可以工作并且速度很快,但不是很优雅。还有其他方法可以得到这个结果吗??
更有效的方法是使用Pandas built-in 函数而不是for
循环。您应该采取两个主要步骤。
首先,不仅要按索引分组,还要按索引和列分组:
res = df.groupby(['ref','value_type']).sum()
print(res)
这一步的输出是这样的:
amount
ref value_type
1 A 120
B 50
2 C 450
3 A 70
其次,需要对multi索引进行unstack,如下:
df2 = res.unstack(level='value_type',fill_value=0)
输出将是您想要的输出:
amount
value_type A B C
ref
1 120 50 0
2 0 0 450
3 70 0 0
作为可选步骤,您可以使用 droplevel
将其展平:
df2.columns = df2.columns.droplevel()
value_type A B C
ref
1 120 50 0
2 0 0 450
3 70 0 0
我有一个包含分类列和数字列的数据框,我想根据分类列的值对数字列(最大、最小、总和...)的值进行一些聚合(所以我有为每个分类列可以采用的每个值创建新列)。
为了更好理解table,最好放个玩具例子
说我有这个数据框:
import pandas as pd
df = pd.DataFrame({
'ref' : [1, 1, 1, 2, 2, 3],
'value_type' : ['A', 'B', 'A', 'C', 'C', 'A'],
'amount' : [100, 50, 20, 300, 150, 70]
}).set_index(['ref'])
value_type amount
ref
1 A 100
1 B 50
1 A 20
2 C 300
2 C 150
3 A 70
我想根据 value_type 的值对金额进行分组,也针对每个参考进行分组。这种情况下的结果(假设只需要求和)将是这个:
df_result = pd.DataFrame({
'ref' : [1, 2, 3],
'sum_amount_A' : [120, 0, 70],
'sum_amount_B' : [50, 0, 0],
'sum_amount_C' : [0, 450, 0]
}).set_index('ref')
sum_amount_A sum_amount_B sum_amount_C
ref
1 120 50 0
2 0 0 450
3 70 0 0
我试过一些可行的方法,但效率极低。大约需要几分钟来处理 30.000 行。
我所做的是这样的:(我有一个数据框,每个索引引用只有一行,称为 df_final)
df_grouped = df.groupby(['ref'])
for ref in df_grouped.groups:
df_aux = df.loc[[ref]]
column = 'A' # I have more columns, but for illustration one is enough
for value in df_aux[column].unique():
df_aux_column_value = df_aux.loc[df_aux[column] == value]
df_final.at[ref,'sum_' + column + '_' + str(value)] = np.sum(df_aux_columna_valor[column])
我相信应该有更好的方法来进行这种聚合...提前致谢!!
编辑:
当只有一列作为分组依据时,给出的答案是正确的。在真实的数据框中,我有几列我想计算一些聚合函数,但分别计算每列的值。我的意思是我不想要列值的每个组合的聚合值,而只是列本身的聚合值。
举个例子
import pandas as pd
df = pd.DataFrame({
'ref' : [1, 1, 1, 2, 2, 3],
'sexo' : ['Hombre', 'Hombre', 'Hombre', 'Mujer', 'Mujer', 'Hombre'],
'lugar_trabajo' : ['Campo', 'Ciudad', 'Campo', 'Ciudad', 'Ciudad', 'Campo'],
'dificultad' : ['Alta', 'Media', 'Alta', 'Media', 'Baja', 'Alta'],
'amount' : [100, 50, 20, 300, 150, 70]
}).set_index(['ref'])
这个数据框看起来像这样:
sexo lugar_trabajo dificultad amount
ref
1 Hombre Campo Alta 100
1 Hombre Ciudad Media 50
1 Hombre Campo Alta 20
2 Mujer Ciudad Media 300
2 Mujer Ciudad Baja 150
3 Hombre Campo Alta 70
如果我按几列分组,或者做一个主元table(据我所知,这在某种程度上是等价的),这样做:
df.pivot_table(index='ref',columns=['sexo','lugar_trabajo','dificultad'],values='amount',aggfunc=[np.sum,np.min,np.max,len], dropna=False)
我将得到一个包含 48 列的数据框(因为我有 3 * 2 * 2 个不同的值和 4 个聚合函数)。
实现我想要的结果的一种方法是:
df_agregado = pd.DataFrame(df.index).set_index('ref')
for col in ['sexo','lugar_trabajo','dificultad']:
df_agregado = pd.concat([df_agregado, df.pivot_table(index='ref',columns=[col],values='amount',aggfunc=[np.sum,np.min,np.max,len])],axis=1)
我一个人做每一组,然后把它们全部拼接起来。通过这种方式,我得到 28 列(2 * 4 + 3 * 4 + 2 * 4)。它可以工作并且速度很快,但不是很优雅。还有其他方法可以得到这个结果吗??
更有效的方法是使用Pandas built-in 函数而不是for
循环。您应该采取两个主要步骤。
首先,不仅要按索引分组,还要按索引和列分组:
res = df.groupby(['ref','value_type']).sum()
print(res)
这一步的输出是这样的:
amount
ref value_type
1 A 120
B 50
2 C 450
3 A 70
其次,需要对multi索引进行unstack,如下:
df2 = res.unstack(level='value_type',fill_value=0)
输出将是您想要的输出:
amount
value_type A B C
ref
1 120 50 0
2 0 0 450
3 70 0 0
作为可选步骤,您可以使用 droplevel
将其展平:
df2.columns = df2.columns.droplevel()
value_type A B C
ref
1 120 50 0
2 0 0 450
3 70 0 0