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

忽略索引中后缀的高效级联

  •  2
  • Cleb  · 技术社区  · 7 年前

    我有两个这样的数据帧:

    import pandas as pd
    
    df1 = pd.DataFrame({"c1": range(5), "c2": range(1, 6)}, index=list("ABCDE"))
    df2 = pd.DataFrame({"c3": range(15, 21), "c4": range(11, 17)}, index=["A_suf1", "B_suf2", "A_suf2", "C_suf2", "B_suf1", "D_suf1"])   
    
       c1  c2    
    A   0   1
    B   1   2
    C   2   3
    D   3   4
    E   4   5
    
            c3  c4
    A_suf1  15  11
    B_suf2  16  12
    A_suf2  17  13
    C_suf2  18  14
    B_suf1  19  15
    D_suf1  20  16
    

    我想变成

           c3  c4  c1
    A_suf1  15  11   0
    B_suf2  16  12   1
    A_suf2  17  13   0
    C_suf2  18  14   2
    B_suf1  19  15   1
    D_suf1  20  16   3
    

    suf1 suf2 df2 . 作为中的条目 c1 在里面 df1 A 如果为0,则它应该出现在条目的连接数据帧中 A_suf1 A_suf2 .

    # store original name of index
    old_index = df2.index
    # temporary column which creates values which are in the the index of df1
    df2['helper'] = df2.reset_index()["index"].apply(lambda x: x.split("_")[0]).tolist()
    # prepare concat
    df2 = df2.set_index("helper")
    # concat
    df_final = pd.concat([df2, df1.loc[:, "c1"]], join="inner", axis=1)
    # reset index to original values
    df_final.index = old_index
    

    这给了我想要的输出。

    然而,它需要相当缓慢的 apply df2型 哪个不在 . 例如,上述代码将在以下情况下失败:

    df2 = pd.DataFrame({"c3": range(15, 22), "c4": range(11, 18)}, index=["A_suf1", "B_suf2", "A_suf2", "C_suf2", "B_suf1", "D_suf1", "F_suf1"])
    
            c3  c4
    A_suf1  15  11
    B_suf2  16  12
    A_suf2  17  13
    C_suf2  18  14
    B_suf1  19  15
    D_suf1  20  16
    F_suf1  21  17
    

    因此,问题是,对于工作和非工作情况,是否分别有更有效和通用的解决方案。

    2 回复  |  直到 6 年前
        1
  •  3
  •   jezrael    7 年前

    使用 join 通过 MultiIndex 创建拆分 index df2 reindex 对于 Multiindex 属于 df1

    df2.index = df2.index.str.split('_', expand=True)
    print(df2)
            c3  c4
    A suf1  15  11
    B suf2  16  12
    A suf2  17  13
    C suf2  18  14
    B suf1  19  15
    D suf1  20  16
    
    print (df1['c1'].reindex(df2.index,level=0))
    A  suf1    0
    B  suf2    1
    A  suf2    0
    C  suf2    2
    B  suf1    1
    D  suf1    3
    Name: c1, dtype: int32
    
    df = df2.join(df1['c1'].reindex(df2.index,level=0))
    #convert MultiIndex to index
    df.index = df.index.map('_'.join)
    print (df)
            c3  c4  c1
    A_suf1  15  11   0
    B_suf2  16  12   1
    A_suf2  17  13   0
    C_suf2  18  14   2
    B_suf1  19  15   1
    D_suf1  20  16   3
    

    为了另一个

    print (df)
            c3  c4   c1
    A_suf1  15  11  0.0
    B_suf2  16  12  1.0
    A_suf2  17  13  0.0
    C_suf2  18  14  2.0
    B_suf1  19  15  1.0
    D_suf1  20  16  3.0
    F_suf1  21  17  NaN
    
        2
  •  1
  •   cs95 abhishek58g    7 年前

    我认为你不需要转换成 MultiIndex . 您只需提取索引并使用 df.loc pd.concat 加入。

    idx = [x[0] for x in df2.index]
    out = pd.concat([df2, df1.loc[idx, ['c1']].set_index(df2.index)], 1)
    print(out)
            c3  c4  c1
    A_suf1  15  11   0
    B_suf2  16  12   1
    A_suf2  17  13   0
    C_suf2  18  14   2
    B_suf1  19  15   1
    D_suf1  20  16   3
    

    对于第二个数据帧,我得到

            c3  c4   c1
    A_suf1  15  11  0.0
    B_suf2  16  12  1.0
    A_suf2  17  13  0.0
    C_suf2  18  14  2.0
    B_suf1  19  15  1.0
    D_suf1  20  16  3.0
    F_suf1  21  17  NaN
    

    # converting to MultiIndex
    100 loops, best of 3: 3.57 ms per loop
    
    # using `df.loc` and `df.set_index`
    1000 loops, best of 3: 1.53 ms per loop