与 pandas 的近似连接

Posted

技术标签:

【中文标题】与 pandas 的近似连接【英文标题】:Approximate join with pandas 【发布时间】:2018-12-14 03:41:53 【问题描述】:

我有 2 个数据框,df1 和 df2。我的两个数据框都有一个名为“zip_code”的列,我想在这些列上加入 df1 和 df2。

问题是,在 df2 中,有时“zip_code”列中的字符串在开头缺少一个“0”。但我希望熊猫能够检测到它们是“相同”的值。

有没有办法在不预处理我的数据的情况下这样做?

【问题讨论】:

您可以用前导零填充字符串,或者将两者都转换为整数,在这种情况下,前导零变得毫无意义(后者不适用于带有破折号的邮政编码,例如01912-001)。 【参考方案1】:

在这种情况下,Series.str.zfill() 可用于预处理。

import pandas as pd
df = pd.DataFrame('zip5': ['1', '12', '123', '1234', '12345', '123456'])

df.zip5.str.zfill(5)
#0     00001
#1     00012
#2     00123
#3     01234
#4     12345
#5    123456
#Name: zip5, dtype: object

这不会影响任何大于或等于 5 个字符的邮政编码,并且会用前导零填充所有内容,在这种情况下最多为 5 个字符。您可以使用它来更新 df2 中的 zip,然后正常合并。

【讨论】:

【参考方案2】:

这会很长,并且假设所有邮政编码在开头附加一个 0 后将具有相同的长度。

import pandas as pd
import numpy as np

t1 = pd.DataFrame('id':[1,2,3,4],
                 'zip_code':['0234','0345','3456','4567'])

t2 = pd.DataFrame('id2':[5,6,7,8],
                 'zip_code':['234','0345','3456','4567'])

t2['lens'] = t2.zip_code.apply(len)

t2.loc[:,'zip_code'] = np.where(t2.lens<4,'0'+t2['zip_code'].astype(str),t2['zip_code'])

输入 t1:

    id  zip_code
0   1   0234
1   2   0345
2   3   3456
3   4   4567

输入 t2:

    id2 zip_code
0   5   234
1   6   0345
2   7   3456
3   8   4567

输出 t2:

    id2 zip_code    lens
0   5   0234    3
1   6   0345    4
2   7   3456    4
3   8   4567    4

如果您以后不需要它,您可以删除镜头列。现在您可以使用 zip_code 连接两个数据帧 t1 和 t2。

【讨论】:

【参考方案3】:

如果不需要,我认为建议进行预处理。否则,当您合并时,您将有 2 个邮政编码的行,一个以 '0' 开头,另一个不是。

您可以根据掩码更新df2 中的违规邮政编码。我假设zip_code 系列都被转换为str

# prefixing with 0 causes a zip_code match with df1
mask = ('0' + df2['zip_code']).isin(df1['zip_code'].unique())

# apply the prefix for these cases
df2.loc[mask, 'zip_code'] = '0' + df2.loc[mask, 'zip_code']

然后像往常一样执行合并。

【讨论】:

【参考方案4】:

只要使用DataFrame的join函数就可以了

import pandas as pd

A = pd.DataFrame(
    
        'zip_code':[1000,1001,2000,2002],
        'place':['A','A','B','B']
    
)

B = pd.DataFrame(
    
        'Name':['x','y','z'],
        'zip_code':[1001,1000,2000]

)
B['zip_code'] = [x.lstrip('0') for x in B['zip_code']]
B.join(A.set_index('zip_code'), on='zip_code')

【讨论】:

我认为这不能回答 OP 关于预先修复缺失 0 的问题。 是的。我错过了一步。它已经过编辑,现在应该可以使用了

以上是关于与 pandas 的近似连接的主要内容,如果未能解决你的问题,请参考以下文章

Python数据分析pandas之数据拼接与连接

将 CSV 文件与 pandas 连接

将 csv 文件与 pandas 连接时内存不足

Pandas:如何将 MultiIndex DataFrame 与单个索引 DataFrame 连接,以及自定义排序

Pandas 与 to_sql 的 ODBC 连接

pandas合并/连接