Python pandas 自定义 unmelt - 从重复的行创建列
Python pandas custom unmelt - create columns from duplicated rows
我有以下数据框:
import pandas as pd
import numpy as np
base_df = pd.DataFrame({
'id': [1,2,3],
'base_value': [100, None, 123.1]
})
id base_value
1 100.0
2 NaN
3 123.1
还有一个:
extended_df = pd.DataFrame({
'id': [1, 1, 2, 2, 3],
'ext_id': [100, 500, 90, 1, 1000],
'role_1': [True, False, False, True, True],
'role_2': [False, True, True, False, False],
'ext_value': [10, 5, 21, 200, 500]
})
id ext_id role_1 role_2 ext_value
1 100 True False 10
1 500 False True 5
2 90 False True 21
2 1 True False 200
3 1000 True False 10
我想得到以下数据框作为结果:
result_df = pd.DataFrame({
'id': [1,2,3],
'base_value': [100, None, 123.1],
'ext_value_role_1': [10, 200, 500],
'ext_value_role_2' :[5, 21, None]
})
id base_value ext_value_role_1 ext_value_role_2
1 100.0 10 5.0
2 NaN 200 21.0
3 123.1 500 NaN
转换背后的逻辑如下。对于 base_df
中的每一行,在 extended_df
中查找匹配项。生成的数据框将包含与 role_*
列乘以 extended_df
中的 ext_value
列数一样多的附加列(不包括 id
、base_value
)。如果 id
的角色设置为 False
,则列中的结果值为 None
。
我想出了下面发布的代码。它适用于小示例,但我希望得到更多 pandas
esque。
def multiply_by_boolean(boolean_value, variable):
if boolean_value is False:
return None
elif boolean_value is None:
raise ValueError('boolean_value cannot be None')
return variable
extended_df['ext_value_role_1'] = extended_df.apply(lambda x: multiply_by_boolean(x['role_1'], x['ext_value']), axis=1)
extended_df['ext_value_role_2'] = extended_df.apply(lambda x: multiply_by_boolean(x['role_2'], x['ext_value']), axis=1)
res_df = extended_df[['id', 'ext_value_role_1', 'ext_value_role_2']]
res_df = res_df.groupby('id').agg('max')
res_df = res_df.merge(right=base_df, left_index=True, right_on='id')
您可以使用 merge
构建一个临时数据框,然后只需添加相关列:
tmp =base_df.merge(extended_df, on='id')
resul_df = base_df.set_index('id')
for role in ['role_1', 'role_2']:
resul_df['ext_value_' + role] = tmp.loc[
tmp[role] == True, ['id', 'ext_value']].set_index('id')
resul_df.reset_index(inplace=True)
它给出了预期的结果:
id base_value ext_value_role_1 ext_value_role_2
0 1 100.0 10 5.0
1 2 NaN 200 21.0
2 3 123.1 500 NaN
我有以下数据框:
import pandas as pd
import numpy as np
base_df = pd.DataFrame({
'id': [1,2,3],
'base_value': [100, None, 123.1]
})
id base_value
1 100.0
2 NaN
3 123.1
还有一个:
extended_df = pd.DataFrame({
'id': [1, 1, 2, 2, 3],
'ext_id': [100, 500, 90, 1, 1000],
'role_1': [True, False, False, True, True],
'role_2': [False, True, True, False, False],
'ext_value': [10, 5, 21, 200, 500]
})
id ext_id role_1 role_2 ext_value
1 100 True False 10
1 500 False True 5
2 90 False True 21
2 1 True False 200
3 1000 True False 10
我想得到以下数据框作为结果:
result_df = pd.DataFrame({
'id': [1,2,3],
'base_value': [100, None, 123.1],
'ext_value_role_1': [10, 200, 500],
'ext_value_role_2' :[5, 21, None]
})
id base_value ext_value_role_1 ext_value_role_2
1 100.0 10 5.0
2 NaN 200 21.0
3 123.1 500 NaN
转换背后的逻辑如下。对于 base_df
中的每一行,在 extended_df
中查找匹配项。生成的数据框将包含与 role_*
列乘以 extended_df
中的 ext_value
列数一样多的附加列(不包括 id
、base_value
)。如果 id
的角色设置为 False
,则列中的结果值为 None
。
我想出了下面发布的代码。它适用于小示例,但我希望得到更多 pandas
esque。
def multiply_by_boolean(boolean_value, variable):
if boolean_value is False:
return None
elif boolean_value is None:
raise ValueError('boolean_value cannot be None')
return variable
extended_df['ext_value_role_1'] = extended_df.apply(lambda x: multiply_by_boolean(x['role_1'], x['ext_value']), axis=1)
extended_df['ext_value_role_2'] = extended_df.apply(lambda x: multiply_by_boolean(x['role_2'], x['ext_value']), axis=1)
res_df = extended_df[['id', 'ext_value_role_1', 'ext_value_role_2']]
res_df = res_df.groupby('id').agg('max')
res_df = res_df.merge(right=base_df, left_index=True, right_on='id')
您可以使用 merge
构建一个临时数据框,然后只需添加相关列:
tmp =base_df.merge(extended_df, on='id')
resul_df = base_df.set_index('id')
for role in ['role_1', 'role_2']:
resul_df['ext_value_' + role] = tmp.loc[
tmp[role] == True, ['id', 'ext_value']].set_index('id')
resul_df.reset_index(inplace=True)
它给出了预期的结果:
id base_value ext_value_role_1 ext_value_role_2
0 1 100.0 10 5.0
1 2 NaN 200 21.0
2 3 123.1 500 NaN