Python 通过部分字符串匹配合并两个数据帧
我正在尝试基于部分字符串匹配合并两个不同大小的相当大的数据帧 df1$代码包含所有12位代码,而df2$代码包含10-12位代码的混合,其中一些较短的代码是与df1$代码中的12位代码相匹配的子字符串 因此,我需要合并两个数据帧之间的所有12位匹配,还需要合并df2中具有10-11位代码的记录,这些记录是与df1的子字符串匹配 数据帧示例:Python 通过部分字符串匹配合并两个数据帧,python,r,Python,R,我正在尝试基于部分字符串匹配合并两个不同大小的相当大的数据帧 df1$代码包含所有12位代码,而df2$代码包含10-12位代码的混合,其中一些较短的代码是与df1$代码中的12位代码相匹配的子字符串 因此,我需要合并两个数据帧之间的所有12位匹配,还需要合并df2中具有10-11位代码的记录,这些记录是与df1的子字符串匹配 数据帧示例: df1 <- data.frame(code_1 = c('123456789012', '210987654321', '567890543211'
df1 <- data.frame(code_1 = c('123456789012', '210987654321', '567890543211', '987656789001', '123456654321', '678905432156', '768927461037', '780125634701', '673940175372', '167438501473'),
name = c('bob','joe','sally','john','lucy','alan', 'fred','stephanie','greg','tom'))
df2 <- data.frame(code_2 = c('123456789012','2109876543','7890543211','98765678900','12345665432','678905432156'),
color = c('blue', 'red', 'green', 'purple', 'orange', 'brown'))
df3 (merged)
code_1 code_2 name color
123456789012 123456789012 bob blue
210987654321 2109876543 joe red
567890543211 7890543211 sally green
987656789001 98765678900 john purple
123456654321 12345665432 lucy orange
678905432156 678905432156 alan brown
在python/pandas中,您可以执行以下操作:
from pandas import DataFrame, Series
df1 = DataFrame(dict(
code1 = ('123456789012', '210987654321', '567890543211', '987656789001', '123456654321', '678905432156', '768927461037', '780125634701', '673940175372', '167438501473'),
name = ('bob','joe','sally','john','lucy','alan', 'fred','stephanie','greg','tom')))
df2 = DataFrame(dict(
code2 = ('123456789012','2109876543','7890543211','98765678900','12345665432','678905432156'),
color = ('blue', 'red', 'green', 'purple', 'orange', 'brown')))
matches = [df1[df1['code1'].str.contains(x)].index[0] for x in df2['code2']]
print(
df1.assign(subcode=Series(data=df2['code2'], index=matches))
.merge(df2, left_on='subcode', right_on='code2')
.drop('subcode', axis='columns')
)
这倒是:
code1 name code2 color
0 123456789012 bob 123456789012 blue
1 210987654321 joe 2109876543 red
2 567890543211 sally 7890543211 green
3 987656789001 john 98765678900 purple
4 123456654321 lucy 12345665432 orange
5 678905432156 alan 678905432156 brown
注意:我讨厌在数据帧中使用循环,但我想这是可行的。根据新信息更新。这应该起作用:
df2$New <- lapply(df2$code_2, grep, df1$code_1,value=T)
combined <- merge(df1,df2, by.x="code_1", by.y="New")
code_1 name code_2 color
1 123456654321 lucy 12345665432 orange
2 123456789012 bob 123456789012 blue
3 210987654321 joe 2109876543 red
4 567890543211 sally 7890543211 green
5 678905432156 alan 678905432156 brown
6 987656789001 john 98765678900 purple
df2$New尝试此SQL连接
library(sqldf)
sqldf("select a.code_1, b.code_2, a.name, b.color
from df2 b left join df1 a on a.code_1 like '%' || b.code_2 || '%'")
给予:
code_1 code_2 name color
1 123456789012 123456789012 bob blue
2 210987654321 2109876543 joe red
3 567890543211 7890543211 sally green
4 987656789001 98765678900 john purple
5 123456654321 12345665432 lucy orange
6 678905432156 678905432156 alan brown
更新:更新答案以反映问题中的更改,以便(1)子字符串可以位于目标字符串中的任何位置,以及(2)代码列的名称已更改为code\u 1
和code\u 2我们可以使用grep
+sapply
从df2$code
中为每个df1$code
提取匹配索引,并从中创建matchID
。接下来,我们在matchID
上进行merge
以获得所需的输出:
df1$matchID = row.names(df1)
df2$matchID = sapply(df2$code, function(x) grep(x, df1$code))
df_merge = merge(df1, df2, by = "matchID")[-1]
请注意,如果df1$code
与任何df2$code
不匹配,df2$matchID
将为空,因此不会与df1$matchID
合并
结果:
> df2
code color matchID
1 123456789012 blue 1
2 2109876543 red 2
3 7890543211 green 3
4 98765678900 purple 4
5 12345665432 orange 5
6 678905432156 brown 6
7 14124124124 black
> df_merge
code.x name code.y color
1 123456789012 bob 123456789012 blue
2 210987654321 joe 2109876543 red
3 567890543211 sally 7890543211 green
4 987656789001 john 98765678900 purple
5 123456654321 lucy 12345665432 orange
6 678905432156 alan 678905432156 brown
df1 <- data.frame(code = c('123456789012', '210987654321', '567890543211', '987656789001', '123456654321', '678905432156', '768927461037', '780125634701', '673940175372', '167438501473'),
name = c('bob','joe','sally','john','lucy','alan', 'fred','stephanie','greg','tom'),
stringsAsFactors = FALSE)
df2 <- data.frame(code = c('123456789012','2109876543','7890543211','98765678900','12345665432','678905432156', '14124124124'),
color = c('blue', 'red', 'green', 'purple', 'orange', 'brown', 'black'),
stringsAsFactors = FALSE)
数据(添加不匹配项以获得更好的演示):
> df2
code color matchID
1 123456789012 blue 1
2 2109876543 red 2
3 7890543211 green 3
4 98765678900 purple 4
5 12345665432 orange 5
6 678905432156 brown 6
7 14124124124 black
> df_merge
code.x name code.y color
1 123456789012 bob 123456789012 blue
2 210987654321 joe 2109876543 red
3 567890543211 sally 7890543211 green
4 987656789001 john 98765678900 purple
5 123456654321 lucy 12345665432 orange
6 678905432156 alan 678905432156 brown
df1 <- data.frame(code = c('123456789012', '210987654321', '567890543211', '987656789001', '123456654321', '678905432156', '768927461037', '780125634701', '673940175372', '167438501473'),
name = c('bob','joe','sally','john','lucy','alan', 'fred','stephanie','greg','tom'),
stringsAsFactors = FALSE)
df2 <- data.frame(code = c('123456789012','2109876543','7890543211','98765678900','12345665432','678905432156', '14124124124'),
color = c('blue', 'red', 'green', 'purple', 'orange', 'brown', 'black'),
stringsAsFactors = FALSE)
df1我们是否可以简单地将每个代码的长度截断为10位,然后进行匹配?您也想要python解决方案吗?在其他人编辑python标记之前,您最初包含了该标记。是否应该将其与'7890543211'
匹配'567890543211'
?或者您只关心出现在12位数字开头的子字符串吗?@useR如果您的示例是所需的结果,您可以使用sapply(df1$code,agrep,df2$code,value=TRUE)
获取匹配值。我不知道如何从列表返回到加入。抱歉,更正了字段。我不能截短到10位,因为有些从开头到结尾都缺少数字(有些从开头到结尾都缺少一个数字)。我可以使用R或Python答案。谢谢他要了一张支票solution@Mako212问题并没有那么明确。考虑到OP包含了一个python标记,而其他人删除了它,我觉得这仍然是一个有效的答案。@Mako212可能值得删除这些注释,因为OP现在已经明确表示python解决方案也在使用sought@PaulH.嗨,我正在尝试使用您的代码在我的数据集上执行此操作,但我得到以下错误:Indexer错误:索引0超出大小为0的轴0的界限。知道为什么吗?谢谢@基本上是句子。两列都有段落,其中一列有另一列句子的子集(两列大小不同)。让我们假设dataframe 1中的第1列有“Hello,今天真是美好的一天!”和“You Do Azing job”这样的值,另一列是这些句子的子集,如“Hello,today”或“You Do an”,我希望第2列中的所有内容(也称为子集)都与它们的适当子集相关联。这有意义吗?我认为这不起作用,因为并不是df2
中的所有10位代码都与df1
@中的前10位匹配。用户更正,如果子字符串从数字内的某个地方开始,它就不起作用,但看看OPs示例,他只返回了5个匹配项,这是前10位数字匹配的地方。请注意,在我更新后,上面的注释不再是问题。我尝试了这一点,但对于完整的数据帧(一个210K+行和另一个30K+行),它不断崩溃。将201K+数据帧拆分为四个数据块在第一个数据块上产生以下错误:顺序错误(列表(“899349002062”),“793573098023”、“815036020027”、“857638004289”:在“orderVector1”中未实现类型“list”