熊猫从df中提取行,其中df ['col']值与df2 ['col']值匹配

时间:2019-07-23 09:28:36

标签: python

发现这一难题很困难,希望您能帮上忙,

我有两个dfdfAdfB。每个字段中都有一个telnumfiledatetime列,但是只有dfA包含一个name列,并且只有dfA具有完整的电话不同于dfB的数字字符串值,该数字字符串值有时具有部分完整的电话号码,最高为x个数字,例如有时,缺少国际调用代码,有时提供的是'0'而不是国际调用代码,而另一些时候,既没有国际调用代码也没有前导'0'。

n还包含比dfA(<10行)更多的数据,但是在两者之间有完整的dfBtimestampfile列总是分别带有日期时间和字符串值(即使telnum并不完全如上所述)。

我想做的是从dfB['telnum']匹配dfA的{​​{1}}中提取行,但是由于dfB['telnum']并不总是完整,因此我需要检查匹配dfA['telnum']的子字符串。

我希望结果为dfB['telnum'],但是返回的结果的左侧为dfA['telnum'],右侧为dfResult,这样我可以看到不同的{{1} }和dfA值。

有什么想法吗?

编辑:

我认为我需要一个内部合并,例如

dfB

但是,由于file并不总是完整的datetime字符串,因此结果不完整。如何通过检查pandas.merge(dfA, dfB, on='telnum', how='inner')是否也是dfB['telnum']的子字符串来获得两者之间的匹配项?

2 个答案:

答案 0 :(得分:1)

在执行任何复杂的联接之前,您需要清除数据。 我不确定您所在的国家/地区情况如何,但是在我的国家/地区,如果删除国际前缀或前导零,则电话号码会变成9位数字。

这是我建议您做的事情:

  1. 清理“ telnum”列:
def remove_non_numbers(string):
    result = ""
    for char in string:
        if char.isnumeric():
            result += char
    return result

# Do this for both dataframes just in case
df["telnum"] = df["telnum"].apply(remove_non_numbers)

  1. 删除前9个前的数字:
def limit9(string):
    if len(string) > 9:
        return string[-9:]
    return string

# Do this for both dataframes
df["telnum"] = df["telnum"].apply(limit9)

  1. 现在您可以尝试合并已清理的DF:
dfResult = pd.merge(dfA, dfB, on='telnum', how='inner')

祝你好运!让我知道它是否有效。

答案 1 :(得分:0)

由于您没有提供任何示例输入或输出,因此根据说明,我在这里尝试。这是一个多重问题,取决于您的电话号码的外观,可以有很多方法。

在这里让我有两个数据框(跳过其他列):dfAdfB

dfA:

           telnum
0   0049123456789
1  00919444454555
2   0092789742893

dfB:

        telnum
0    123456789
1  09444454555

首先,让我们清理dfB中的数字。 dfB可以包含以下数字:

  • 带有ISD代码的数字-例如00918888888888
  • 前面带有0的数字08888888888
  • 仅数字-8888888888

我正在剥离每个以0开头的数字。因此,具有国际代码0091的任何内容都将变为091,或者具有091并变为91,并且具有0888888888成为888888888。这是因为,由于您的dfA具有ISD代码的完整编号(我认为格式为00xxNNNNNNNN-格式),因此应该容易找到子字符串匹配项。

dfB['telnum'] = dfB['telnum'].apply(lambda x : x[1:] if x.startswith("0") else x)

dfB现在看起来像(注意第一个出现的0已被剥离):

       telnum  
0   123456789 
1  9444454555 

从dfB中获取所有数字并将其转换为列表:

tempList = dfB['telnum'].tolist()

现在在另一个数据框中寻找匹配项:

dfA[dfA.telnum.str.contains('|'.join(tempList))]

您现在应该得到:

           telnum
0   0049123456789
1  00919444454555

因此,您找到了与之匹配的数字。现在,您可以继续执行这些行,并与其他列或所需的任何内容进行必要的连接。