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 列数一样多的附加列(不包括 idbase_value)。如果 id 的角色设置为 False,则列中的结果值为 None

我想出了下面发布的代码。它适用于小示例,但我希望得到更多 pandasesque。

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