【问题标题】:insert multiple columns based on column name with partial match根据部分匹配的列名插入多列
【发布时间】:2021-08-01 21:43:43
【问题描述】:

我认为这里会有一个简单的解决方案,但我错过了一些东西......

我有两个数据框。一个原始的,第二个带有一些处理过的数据。第二个数据框中的列名与第一个数据框中的列部分匹配。有多个列名部分匹配。来自第二个数据帧的多个列需要重新插入到相同位置,在原始数据帧中具有一个部分匹配的列名(因此,数据帧的大小自然会增加)。下面复制了数据和预期输出的示例。它需要是“程序化的”,因为我有很多这些列/实例。

任何 cmets 都对我很有帮助。

非常感谢!

原始数据

df1 = {'id': ['1','2','3','4'],
        'ab': ['1', '2', '3', '4'],
        'xy': ['1', '2', '3','4'],
        'cd': ['1', '2', '3','4'],
        'ef':['1', '2', '3', '4'],
        'lm':['1', '2', '3', '4'],
        'fa':['1', '2', '3', '4'] }

df1 = pd.DataFrame(df1, columns = ['id','ab', 'xy', 'cd', 'ef', 'lm', 'fa'])

处理过的数据

df2 = {'id': ['1','2','3','4'],
        'ab? op':  ['green', 'red', 'blue', 'None'],
        'ab? 1': ['red', 'yellow', 'None', 'None'],
        'cd': ['L', 'XL', 'M','L'],
        'efab? cba' : ['husband', 'wife', 'husband', 'None'],
        'efab? 1':['son', 'grandparent', 'son', 'None'],
        'efab? 2':['None', 'son', 'None', 'None'],
        'fab? 4':['9', '10', '5', '3'], 
        'fab? po':['England', 'Scotland', 'Wales', 'NA'] }

df2 = pd.DataFrame(df2, columns = ['id','ab? op', 'ab? 1', 'cd', 'efab? cba', 'efab? 1', 'efab? 2', 'fab? 4', 'fab? po'])

预期输出

e = {'id': ['1','2','3','4'],
        'ab? op':  ['green', 'red', 'blue', 'None'],
        'ab? 1': ['red', 'yellow', 'None', 'None'],
        'xy': ['1', '2', '3','4'], 
        'cd': ['L', 'XL', 'M','L'],
        'lm':['1', '2', '3', '4'], 
        'efab? cba' : ['husband', 'wife', 'husband', 'None'],
        'efab? 1':['son', 'grandparent', 'son', 'None'],
        'efab? 2':['None', 'son', 'None', 'None'],
        'fab? 4':['9', '10', '5', '3'], 
        'fab? po':['England', 'Scotland', 'Wales', 'NA'] }

expected = pd.DataFrame(e, columns = ['id','ab? op', 'ab? 1', 'xy', 'cd', 'lm', 'efab? cba', 'efab? 1', 'efab? 2', 'fab? 4', 'fab? po'])

【问题讨论】:

    标签: python pandas rename string-matching partial


    【解决方案1】:

    如果是 Python 3.8+,那么

    result = pd.concat([df1[col]
                        if (candidate := df2.loc[:, df2.columns.str.startswith(col)]).empty
                        else candidate
                        for col in df1],
                       axis=1)
    

    对于df1 的每一列,我们在df2 中查找candidate 列,即startswithdf1 中的列名。如果存在这样的列,则将候选列放在结果中,否则将列保留在df1

    得到

      id ab? op   ab? 1 xy  cd efab? cba      efab? 1 efab? 2 lm fab? 4   fab? po
    0  1  green     red  1   L   husband          son    None  1      9   England
    1  2    red  yellow  2  XL      wife  grandparent     son  2     10  Scotland
    2  3   blue    None  3   M   husband          son    None  3      5     Wales
    3  4   None    None  4   L      None         None    None  4      3        NA
    

    如果是 3.8-,

    cols = []
    for col in df1:
        candidate = df2.loc[:, df2.columns.str.startswith(col)]
        cols.append(df1[col] if candidate.empty else candidate)
    
    result = pd.concat(cols, axis=1)
    

    【讨论】:

    • 感谢您的意见!所以这适用于大多数列,但它会复制一些名称中只有一个单词或字母差异的列。你知道这是为什么吗?
    • @br101 您能否更具体地描述“部分匹配”的描述?我假设 startswith 但显然在您的某些情况下该假设失败了。
    • 道歉 - 一些列名仅因单个字母而不同 - 在问号之前。例如,原始列可能是“在过去 12 个月中,您有过吗?”或“在过去的 12 个月里你去过吗?”在第二个数据框中将是'在过去的 12 个月里你有过吗? Covid19','在过去的 12 个月里,你有过吗?食物中毒','在过去的 12 个月里,你有过吗?到 A&E' 等。问号之前唯一不同的词是/已经(我试图在示例中使其简单,但我使它变得更加困难)。谢谢你的帮助!
    • @br101 恐怕我没有完全理解。也许您可以举一些例子并更新问题本身,或者您可能想问另一个问题,其他人可能会理解并提出解决方案,对不起。
    • 抱歉,您是对的,它不再特别清楚了 - oi 在此处发布了一个新问题,其中包含一些不同的示例数据。可能有帮助。再次感谢!! stackoverflow.com/questions/67490826/…
    【解决方案2】:

    与两个带有修改的列名称的差异结合后,argsort 的东西

    c2 = df2.columns.str[:2]
    c1 = df1.columns
    x = pd.concat([df2,df1[c1[~c1.isin(c2)]]],axis=1)
    x = x.iloc[:,x.columns.str[:2].map(dict(zip(c1,range(len(c1))))).argsort()]
    x
    Out[115]: 
      id ab? op   ab? 1 xy  cd efab? cba      efab? 1 efab? 2 lm fab? 4   fab? po
    0  1  green     red  1   L   husband          son    None  1      9   England
    1  2    red  yellow  2  XL      wife  grandparent     son  2     10  Scotland
    2  3   blue    None  3   M   husband          son    None  3      5     Wales
    3  4   None    None  4   L      None         None    None  4      3        NA
    

    【讨论】:

      猜你喜欢
      • 2013-02-28
      • 1970-01-01
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      • 2020-10-28
      • 2021-03-28
      • 2014-02-12
      • 2023-02-20
      相关资源
      最近更新 更多