3

Stata 用户会知道,在合并数据时_merge会生成一个变量,该变量通过_merge1 表示该merge观察成功,通过 2 表示观察仅在主数据集中,或通过 3 表示观察仅在使用数据集中。我正在尝试通过编写自己的函数在熊猫中重新创建它。我有以下工作:

def MergeReport(DF1, DF2, keys, HOW = 'outer'):

    if len(keys) == 1:
        KeysDF1 = set(DF1[keys[0]])
        KeysDF2 = set(DF2[keys[0]])
        MasterError = list(KeysDF1.difference(KeysDF2))
        UsingError = list(KeysDF2.difference(KeysDF1))
        MG = pd.merge(DF1, DF2, on = keys, how = HOW)
        MG['_merge'] = None

        for row in MG.index:
            if MG[keys[0]][row] in MasterError:
                MG['_merge'][row] = "merge_2"
            elif MG[keys[0]][row] in UsingError:
                MG['_merge'][row] = "merge_3"
            else:
                MG['_merge'][row] = "merge_1"

        return MG       

    else:
        KeysDF1 = set(zip(DF1[keys[0]], DF1[keys[1]]))      
        KeysDF2 = set(zip(DF2[keys[0]], DF2[keys[1]]))          
        MasterError = list(KeysDF1.difference(KeysDF2)) 
        UsingError = list(KeysDF2.difference(KeysDF1))
        MG = pd.merge(DF1, DF2, on = keys, how = HOW)
        MG['_merge'] = None

        for row in MG.index:
            if tuple([MG[keys[0]][row], MG[keys[1]][row]]) in MasterError:
                MG['_merge'][row] = "merge_2"
            elif tuple([MG[keys[0]][row], MG[keys[1]][row]]) in UsingError:
                MG['_merge'][row] = "merge_3"
            else:
                MG['_merge'][row] = "merge_1"

        return MG   

参数是 DataFrame1、DataFrame2、“键”列表(即要合并的列)和一个可选参数 HOW,该参数传递给 pd.merge 参数 how = HOW。最终,参数将扩展到 pd.merge 函数中的所有参数。

我的问题很明显:我不知道如何编写代码以使其可以接受任意长度的键列表。我的问题发生在这里:

KeysDF1 = set(zip(DF1[keys[0]], DF1[keys[1]]))      
KeysDF2 = set(zip(DF2[keys[0]], DF2[keys[1]]))

我无法弄清楚如何编写这个,以便我可以遍历任意长度的键列表。特别是我尝试了列表理解:

KeysDF1 =   set(zip(tuple([DF1[keys[x]] for x in range(len(keys))])))   

但这不起作用,因为“系列对象是可变的,它们不能被散列”。我想我也会在代码中发现类似的问题:

if tuple([MG[keys[0]][row], MG[keys[1]][row]]) in MasterError:
    MG['_merge'][row] = "merge_2"

编辑:在另一位用户的建议下,我发布了实现相同目标的替代方法。我不建议将此作为问题本身的解决方案,而只是一种避免该问题的方法:

def MergeReport(DF1, DF2, how = 'inner', on = None, left_on = None, right_on = None, \    left_index = False, right_index = False, \sort = False, suffixes = ('_x', '_y'), copy = True):
    DF1['Master'] = 1
    DF2['Using'] = 2

    MDF = pd.merge(DF1, DF2, how = how, on = on, left_on = left_on, right_on = right_on, left_index = left_index, right_index = right_index, \
sort = sort, suffixes = suffixes, copy = copy)

    MDF['Master'].fillna(value = 0, inplace = True)
    MDF['Using'].fillna(value = 0, inplace = True)
    MDF['_Merge'] = MDF['Master'] + MDF['Using']
    del MDF['Master']
    del MDF['Using']
    List = ['1_MasterOnly', '2_UsingOnly', '3_Matched']
    LIST = [List[int(MDF['_Merge'][row] - 1)] for row in MDF.index]
    MDF['_Merge'] = np.array(LIST)
    return MDF
4

1 回答 1

0

不确定我理解正确,但概括

KeysDF1 = set(zip(DF1[keys[0]], DF1[keys[1]]))

在我看来不是

KeysDF1 =   set(zip(tuple([DF1[keys[x]] for x in range(len(keys))])))

反而

KeysDF1 =   set(zip(*tuple([DF1[keys[x]] for x in range(len(keys))])))

或者干脆

KeysDF1 =   set(zip(*[DF1[keys[x]] for x in range(len(keys))]))
于 2013-10-08T12:43:08.217 回答