代码之家  ›  专栏  ›  技术社区  ›  PeCaDe

pandas使用列表值在列上左联接

  •  0
  • PeCaDe  · 技术社区  · 8 年前

    对于这两个数据示例,我希望通过一列进行联接,该列在左联接数据框中的值是多个元素中的一个元素的列表,而在另一个数据框中的值是相同的列(主键),其中包含没有列表作为格式的附加信息。

    用这个例子

    df1 = pd.DataFrame({'ID':[[1111],[2222,3333],[4444,5555],[6666]],'NAME':['foo','bar','zoo','bahh']})
    df2 = pd.DataFrame({'ID':[[1111],[2222],[3333],[4444],[5555],[7777]],'ALT_NAME':['foo_alt','bar_alt','zoo_alt','baoo','razz','foo fi']})
        print(df1)
        print(df2)
    

    输出〔1〕:

        ID              NAME
    0   [1111]          foo
    1   [2222, 3333]    bar
    2   [4444, 5555]    zoo
    3   [6666]          bahh
    

    输出〔2〕:

        ALT_NAME    ID
    0   foo_alt     [1111]
    1   bar_alt     [2222]
    2   wis_alt     [3333]
    3   baoo        [4444]
    4   razz        [5555]
    5   foo fi      [7777]
    

    结果应该是:

        ID              NAME    ALT NAME
    0   [1111]          foo     [foo_alt]       
    1   [2222, 3333]    bar     [bar_alt , wis_alt]
    2   [4444, 5555]    zoo     [baoo, razz]        
    3   [6666]          bahh    nan
    

    建议的解决方案:

    我可以通过将ID拆分成几列并执行几个左联接来解决这个问题,但是我希望找到一个更为智能的解决方案。所以,这个问题的本质是更面向Python学习。

    2 回复  |  直到 8 年前
        1
  •  2
  •   Anton vBR    8 年前

    您应该将输出[2]转换为地图(熊猫系列),例如:

    df2.ID = df2.ID.apply(lambda x: x[0])
    s2 = df2.set_index('ID')['ALT_NAME'] # let us rename it s2 as it is a series now!
    

    完成后,您可以简单地使用apply和fetch值,并进行列表理解:

    df1['ALT NAME'] = df1.ID.apply(lambda x: [s2.get(i,None) for i in x])
    print(df1)
    

    返回:

                 ID  NAME            ALT NAME
    0        [1111]   foo           [foo_alt]
    1  [2222, 3333]   bar  [bar_alt, zoo_alt]
    2  [4444, 5555]   zoo        [baoo, razz]
    3        [6666]  bahh              [None]
    

    小评论 :这不会给你 nan 在最后一行。但是,如果你有一场比赛和一场没有比赛,那不是[比赛1,没有]吗?.

    转换为s2后的df2:

    ID
    1111    foo_alt
    2222    bar_alt
    3333    zoo_alt
    4444       baoo
    5555       razz
    7777     foo fi
    

    单行版本: s2 = df2.assign(ID=df2.ID.apply(lambda x: x[0])).set_index('ID')['ALT_NAME']

        2
  •  0
  •   paveltr    8 年前

    我只是创建了额外的列作为字符串类型,并在上面进行了联接。

    df1['ID_STR'] = df1['ID'].astype(str)
    df2['ID_STR'] = df2['ID'].astype(str)
    
    df = pd.merge(df1, df2, how = 'left', on = 'ID_STR')