【问题标题】:Efficient concatenation ignoring suffixes in index忽略索引中的后缀的有效连接
【发布时间】:2017-09-03 17:09:18
【问题描述】:

我确实有两个这样的数据框:

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

所以,我想在df2 的索引中连接独立于后缀suf1suf2 的数据帧。由于df1df1A 列的条目为0,因此它应该出现在条目A_suf1A_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 中有一个不在df1 中的索引条目,它也会失败。例如,上面的代码对于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

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

【问题讨论】:

    标签: python performance pandas dataframe concat


    【解决方案1】:

    使用joinMultiIndex 创建拆分indexdf2reindex 用于Multiindexdf1

    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
    

    另一个df2 获取:

    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
    

    【讨论】:

    • 非常好(点赞)!似乎有效地解决了我的两个问题。
    • @cᴏʟᴅsᴘᴇᴇᴅ - 是的,这是另一种解决方案。祝你好运!
    【解决方案2】:

    我认为您不需要转换为MultiIndex。您只需提取索引并使用df.locpd.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
    

    【讨论】:

    • 谢谢,似乎也可以正常工作(赞成);仍然需要弄清楚为什么split 不会出现在任何地方。 ;)
    猜你喜欢
    • 1970-01-01
    • 2023-01-25
    • 2020-12-08
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 2019-05-07
    相关资源
    最近更新 更多