【问题标题】:Python merge multiple substringsPython合并多个子字符串
【发布时间】:2021-02-22 10:48:18
【问题描述】:

我有以下数据框:

import pandas as pd

df1 = pd.DataFrame({'Name':['Jon','Alex','Jenny','Rick','Joe'], 'Color':['Red', 'Blue', 'Green', 'Black', 'Yellow'], 'Tel':['3745 569', '785 985', '635 565a', '987', np.nan]})
df2 = pd.DataFrame({'Phone':['987 856','985',np.nan, '569','459 56']})

我想:

  1. 查找存储在 df1['Tel'] 和 df2['Phone] 列中的公共子字符串值
  2. 左合并 df2,输出电话,df1['Tel'] 和 df1['Colour'] 列中的公共子字符串值。

预期结果:

我找到并编辑的是一个代码,它只能在没有 NaN 值的情况下工作,如果键是像我这样的子字符串,则无法搜索:

a = ['Tel', 'Phone']
b = [1 ,2]
rhs ={}

for x,y in zip(a, b):
    rhs[y] = (df1[x].apply(lambda x: df2[df2['Phone'].str.find(x).ge(0)]['colour']).bfill(axis=1).iloc[:, 0])

【问题讨论】:

    标签: python pandas merge substring nan


    【解决方案1】:

    因此,如果我理解正确,您想通过公共子字符串进行合并。这段代码做到了这一点,虽然不是很优雅。但是我保持明确以显示潜在的陷阱:此代码假定匹配最长的子字符串(可能有较短的匹配,并且确实可能​​存在相同公共长度的多个匹配;此代码不处理该问题,来自 RosettaCode 的最长公共子字符串,参考给出)。

    import pandas as pd
    import numpy as np
    
    # https://rosettacode.org/wiki/Longest_common_substring#Python
    def longestCommon(s1, s2):
        len1, len2 = len(s1), len(s2)
        ir, jr = 0, -1
        for i1 in range(len1):
            i2 = s2.find(s1[i1])
            while i2 >= 0:
                j1, j2 = i1, i2
                while j1 < len1 and j2 < len2 and s2[j2] == s1[j1]:
                    if j1-i1 >= jr-ir:
                        ir, jr = i1, j1
                    j1 += 1; j2 += 1
                i2 = s2.find(s1[i1], i2+1)
        return len(s1[ir:jr+1])
    
    df1 = pd.DataFrame({'Name':['Jon','Alex','Jenny','Rick','Joe'], 'Color':['Red', 'Blue', 'Green', 'Black', 'Yellow'], 
                        'Tel':['3745 569', '785 985', '635 565a', '987', np.nan]})
    df2 = pd.DataFrame({'Phone':['987 856','985', np.nan, '569','459 56']})
    
    # left merge df2 to df1 via longest matching substring Tel to Phone
    mrglst = []
    for phone in df2['Phone']:
        lgstr = 0
        lgtel = ''
        lgcol = ''
        for tidx, trow in df1.iterrows():
            if str(phone) != 'nan' and str(trow['Tel']) != 'nan':
                thisstrl = longestCommon(phone, trow['Tel'])
                if thisstrl > lgstr:
                    lgstr = thisstrl
                    lgtel, lgcol = trow['Tel'], trow['Color']
        mrglst.append([phone, lgtel, lgcol])
        
    dfmrg = pd.DataFrame(mrglst, columns=['Phone', 'Tel', 'Color'])
    print(dfmrg)
    

    这会产生

         Phone       Tel  Color
    0  987 856       987  Black
    1      985   785 985   Blue
    2      NaN                 
    3      569  3745 569    Red
    4   459 56  3745 569    Red
    

    这几乎是所需的输出,但对于最后一行:_56 匹配到 _56 Tel:这是正确的,但可能只需要数字匹配。在这种情况下,最好在匹配之前清理电话号码(其中一个号码末尾有一个“a”,所以我进行了常规字符串匹配)。

    【讨论】:

      猜你喜欢
      • 2018-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      • 2018-01-22
      • 1970-01-01
      • 2019-06-26
      • 2021-06-13
      相关资源
      最近更新 更多