pandas 如何合并两个数据集上不完整的列?

uxh89sit  于 2023-01-28  发布在  其他
关注(0)|答案(3)|浏览(129)

我想合并'key 1'和'key 2'列上的两个数据集,以便在缺少值的情况下,例如在'key 2'列中,它将采用属于第一个键的第二个键的所有组合。

def merge_nan_as_any(mask, data, on, how)
        ...

    mask = pd.DataFrame({'key1': [1,1,2,2],
                         'key2': [None,3,1,2],
                         'value2': [1,2,3,4]})
    data = pd.DataFrame({'key1': [1,1,1,2,2,2],
                         'key2': [1,2,3,1,2,3],
                         'value1': [1,2,3,4,5,6]})

    result = merge_nan_as_any(mask, data, on=['key1', 'key2'], how='left')

    result = pd.DataFrame({'key1': [1,1,1,1,2,2],
                           'key2': [1,2,3,3,1,2],
                           'value2': [1,1,1,2,3,4],
                           'value1': [1,2,3,3,4,5]})

第二个键缺少一个值,因此它从第二个数据集中获取满足以下条件的所有行:key 1必须等于1,key 2是第二个数据集中的任意第二个键值。怎么做?
我想到的第一个明显的解决方案是迭代第一个数据集,并过滤出满足条件的组合,第二个是将第一个数据集拆分为几个数据集,使它们在相同的列中具有NaN,并在具有值的列中合并每个数据集。
但我不喜欢这些解决方案,我想还有更优雅的方法来做我想做的事情。
我将感激任何帮助!

92dk7w1h

92dk7w1h1#

简单的方法,针对非NaN值合并key1/key2,仅针对NaN值合并key1,并且concat

m = mask['key2'].notna()

result = pd.concat([data.merge(mask[~m].drop(columns='key2'), on='key1'),
                    data.merge(mask[m], on=['key1', 'key2']),
                   ], ignore_index=True)

输出:

key1  key2  value1  value2
0     1     1       1       1
1     1     2       2       1
2     1     3       3       1
3     1     3       3       2
4     2     1       4       3
5     2     2       5       4
xnifntxz

xnifntxz2#

开始,我会用另一个 Dataframe 中所有唯一值的列表填充空值;然后,分解它以获得所有可能的组合并转换回数值;最后,将它们合并以获得预期的输出:

mask['key2'] = mask['key2'].fillna(' '.join([str(x) for x in data['key2'].unique()])).astype(str).str.split(' ')
mask = mask.explode('key2')
mask['key2'] = pd.to_numeric(mask['key2'])
pd.merge(mask,data,on=['key1','key2'],how='left')

输出:

key1  key2  value2  value1
0     1     1       1       1
1     1     2       1       2
2     1     3       1       3
3     1     3       2       3
4     2     1       3       4
5     2     2       4       5
nimxete2

nimxete23#

使用pandasql会很容易:

mask.sql("""
    select data.*,self.value2
    from self left join data
    on self.key1=data.key1 and (self.key2=data.key2 or self.key2 is null)
""",**globals())

输出:

key1  key2  value1  value2
0     1     1       1       1
1     1     2       2       1
2     1     3       3       1
3     1     3       3       2
4     2     1       4       3
5     2     2       5       4

相关问题