继续这个问题:python - Group by and add new row which is calculation of other rows
我有一个pandas数据帧如下:
col_1 col_2 col_3 col_4
a X 5 1
a Y 3 2
a Z 6 4
b X 7 8
b Y 4 3
b Z 6 5
我希望,对于col_1中的每个值,应用一个函数,其中col_3和col_4(以及更多列)中的值与col_2中的X和Z相对应,并使用这些值创建一个新行。所以输出如下:
col_1 col_2 col_3 col_4
a X 5 1
a Y 3 2
a Z 6 4
a NEW * *
b X 7 8
b Y 4 3
b Z 6 5
b NEW * *
其中*
是函数的输出。
原始问题(只需要简单的添加)回答:
new = df[df.col_2.isin(['X', 'Z'])]\
.groupby(['col_1'], as_index=False).sum()\
.assign(col_2='NEW')
df = pd.concat([df, new]).sort_values('col_1')
我现在正在寻找一种使用自定义功能的方法,例如(X/Y)
或((X+Y)*2)
,而不是X+Y
。如何修改此代码以符合我的新要求?
答案 0 :(得分:3)
我不确定这是不是你想要的,但是这里有:
def f(x):
y = x.values
return y[0] / y[1] # replace with your function
而且,对new
的更改是:
new = (
df[df.col_2.isin(['X', 'Z'])]
.groupby(['col_1'], as_index=False)[['col_3', 'col_4']]
.agg(f)
.assign(col_2='NEW')
)
col_1 col_3 col_4 col_2
0 a 0.833333 0.25 NEW
1 b 1.166667 1.60 NEW
df = pd.concat([df, new]).sort_values('col_1')
df
col_1 col_2 col_3 col_4
0 a X 5.000000 1.00
1 a Y 3.000000 2.00
2 a Z 6.000000 4.00
0 a NEW 0.833333 0.25
3 b X 7.000000 8.00
4 b Y 4.000000 3.00
5 b Z 6.000000 5.00
1 b NEW 1.166667 1.60
我对f
抱有信心,并假设这些列在它们命中之前已经排序。如果不是这种情况,则需要额外sort_values
次呼叫:
df = df.sort_values(['col_1, 'col_2'])
应该做的伎俩。
答案 1 :(得分:3)
def foo(df):
# Expand variables into dictionary.
d = {v: df.loc[df['col_2'] == v, ['col_3', 'col_4']] for v in df['col_2'].unique()}
# Example function: (X + Y ) * 2
result = (d['X'].values + d['Y'].values) * 2
# Convert result to a new dataframe row.
result = result.tolist()[0]
df_new = pd.DataFrame(
{'col_1': [df['col_1'].iat[0]],
'col_2': ['NEW'],
'col_3': result[0],
'col_4': result[1]})
# Concatenate result with original dataframe for group and return.
return pd.concat([df, df_new])
>>> df.groupby('col_1').apply(lambda x: foo(x)).reset_index(drop=True)
col_1 col_2 col_3 col_4
0 a X 5 1
1 a Y 3 2
2 a Z 6 4
3 a NEW 16 6
4 b X 7 8
5 b Y 4 3
6 b Z 6 5
7 b NEW 22 22
答案 2 :(得分:0)
一种更新的方法(应该提供性能优势)将使用PyArrow和pandas_udf支持向量化操作,如Spark 2.4中所述:PySpark Usage Guide for Pandas with Apache Arrow