与 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 的近似连接的主要内容,如果未能解决你的问题,请参考以下文章