我想识别数据框中彼此高度相似但不一定完全重复的行。我考虑过将每行中的所有数据合并到一个字符串单元格中,然后使用部分匹配函数。能够设置/调整限定匹配所需的相似度(例如,返回与另一行中75%的字符匹配的所有行)将是很好的。
这是一个简单的工作示例。
df<-data.frame(name = c("Andrew", "Andrem", "Adam", "Pamdrew"), id = c(12334, 12344, 34345, 98974), score = c(90, 90, 83, 95))
在这种情况下,我希望第2行显示为第1行的副本,但不是第4行(它太不相似)。感谢您的任何建议。
答案 0 :(得分:1)
您可以使用agrep
(或agrepl
)进行部分(模糊)模式匹配。
> df[agrep("Andrew", df$name), ]
name id score
1 Andrew 12334 90
2 Andrem 12344 90
因此,这表明在匹配“Andrew”时都会找到第1行和第2行然后你可以删除重复项(只接受第一次“安德鲁”匹配)
> a <- agrep("Andrew", df$name)
> df[c(a[1], rownames(df)[-a]), ]
name id score
1 Andrew 12334 90
3 Adam 34345 83
4 Pamdrew 98974 95
答案 1 :(得分:1)
您可以使用agrep
但首先您需要连接所有列以在所有列中进行模糊搜索,而不仅仅是第一列。
xx <- do.call(paste0,df)
df[agrep(xx[1],xx,max=0.6*nchar(xx[1])),]
name id score
1 Andrew 12334 90
2 Andrem 12344 90
4 Pamdrew 98974 95
请注意,对于0.7,您将获得所有行。
一旦匹配行,您应该从data.frame中提取它们,并为其他行重复相同的过程(此处第3行包含其余数据)...
答案 2 :(得分:0)
您可以对名称使用一些近似字符串距离度量标准,例如:
adist(df$name)
[,1] [,2] [,3] [,4]
[1,] 0 1 4 3
[2,] 1 0 3 4
[3,] 4 3 0 6
[4,] 3 4 6 0
或使用异化矩阵计算:
require(cluster)
daisy(df[, c("id", "score")])
Dissimilarities :
1 2 3
2 10
3 22011 22001
4 86640 86630 64629
答案 3 :(得分:0)
扩展agstudy提供的解决方案(参见上面的评论)我制作了以下解决方案,该解决方案生成了一个数据框,其中每个相似的行在数据框中彼此相邻。
df<-data.frame(name = c("Andrew", "Andrem", "Adam", "Pamdrew", "Adan"), id = c(12334, 12344, 34345, 98974, 34344), score = c(90, 90, 83, 95, 83))
xx <- do.call(paste0,df) ## concatenate all columns
df3<-df[0,] ## empty data frame for storing loop results
for (i in 1:nrow(df)){ ## produce results for each row of the data frame
df2<-df[agrep(xx[i],xx,max=0.3*nchar(xx[i])),] ##set level of similarity required (less than 30% dissimilarity in this case)
if(nrow(df2) >= 2){df3<-rbind(df3, df2)} ## rows without matches returned themselves...this eliminates them
df3<-df3[!duplicated(df3), ] ## store saved values in df3
}
我确信有更简洁的方法可以产生这些结果,但这可以完成工作。