R:搜索类似字符串并返回条件符号
My df有以下条目:R:搜索类似字符串并返回条件符号,r,similarity,R,Similarity,My df有以下条目: A xxx xxx xxx1 xx1x yyyy gggg 我想根据a列的相似性,根据以下条件,向df的B列添加符号 我将阈值设置为=或>75% 类似的 列A已排序。所以 检查上面的相似性 这是需要的 如果上一个类似,则符号 将从上面的B列复制 如果上一个不同,则 符号将从同一行的A列复制 例如,因为第1行和第2行是相同的。其符号与A列相同。与第3行相同(4个字母中的3个字母具有相同的字母且顺序相同),75%与第1行和第2行相似。B列中的sybmol将从上一列即xx
A
xxx
xxx
xxx1
xx1x
yyyy
gggg
我想根据a列的相似性,根据以下条件,向df的B列添加符号
- 我将阈值设置为=或>75% 类似的
- 列A已排序。所以 检查上面的相似性 这是需要的
- 如果上一个类似,则符号 将从上面的B列复制
- 如果上一个不同,则 符号将从同一行的A列复制
A B
xxx xxx
xxx xxx
xxx1 xxx
xx1x xx1x
yyyy yyyy
gggg gggg
我通过猜测计算出这个相似度%(如果有用于字符串相似度搜索的形式化方法,则不需要使用它),如果有用于检查R中字符串相似度的形式化方法,则可以很好地使用它
您是否介意指导如何使用R高效地添加此符号列?设置数据:
x=c("xxx", "xxx", "xxx1", "xx1x", "yyyy", "gggg")
守则:
same <- sapply(seq(length(x)-1),
function(i)any(agrep(x[i+1], x[1], max.distance=0.25)))
ex <- embed(x, 2)
cbind(A=x, B=c(x[1], ifelse(same, ex[, 2], ex[, 1])))
它为什么有效 一些关键概念和真正有用的功能: 首先,
agrep
使用Levenshtein编辑距离
测试字符串的相似程度,该距离有效地计算将一个字符串转换为另一个字符串所需的单个字符更改的数量。参数max.distance=0.25
表示允许25%的图案字符串不同
例如,测试是否有任何原始字符串类似于“xxx”:这将返回1:4:
agrep("xxx", x, max.distance=0.25)
[1] 1 2 3 4
其次,embed
提供了一种测试滞后变量的有用方法。例如,embed(x,2)将
x`转换为滞后数组。这使得比较x[1]和x[2]变得很容易,因为它们现在位于阵列中的同一行上:
embed(x, 2)
[,1] [,2]
[1,] "xxx" "xxx"
[2,] "xxx1" "xxx"
[3,] "xx1x" "xxx1"
[4,] "yyyy" "xx1x"
[5,] "gggg" "yyyy"
最后,我使用cbind
和向量子集将原始向量和新向量缝合在一起
为了在数据帧而不是向量上实现这一点,我将代码转换为一个函数,如下所示:
df <- data.frame(A=c("xxx", "xxx", "xxx1", "xx1x", "yyyy", "gggg"))
f <- function(x){
x <- as.vector(x)
same <- sapply(seq(length(x)-1),
function(i)any(agrep(x[i+1], x[1], max.distance=0.25)))
ex <- embed(x, 2)
c(x[1], ifelse(same, ex[, 2], ex[, 1]))
}
df$B <- f(df$A)
df
A B
1 xxx xxx
2 xxx xxx
3 xxx1 xxx
4 xx1x xxx1
5 yyyy yyyy
6 gggg gggg
df这里有一个更“基本”的解决方案(经过编辑以修复评论中提出的一些问题):
dat等等,OP不希望B下的第四个条目是'xx1x'吗?是的,他希望,但他也承认他猜到了值agrep
使用更改含义的正式定义,默认情况下配置为将所有的修改、删除和插入作为一个更改进行计数。因此,在这个例子中有两个变化。这在某种程度上可以在agrep
的参数中进行配置。有关详细信息,请参阅agrep。感谢您的精彩代码。如果我的输入是df列而不是列表,您是否介意给我一些关于如何修改代码的指导?非常感谢,谢谢。我可能误解了您代码的使用。你能教我怎么解决这个问题吗?>dat-dat$B>tmp-dat$B[1]for(i in 2:length(tmp)){+x=0.75){+dat$B[i]我相信问题在于,我已经配置了R,在创建数据帧时将字符向量作为字符;默认设置是将它们强制为因子。strsplit
需要一个字符向量,而不是因子。如果使用strsplit(as.character(dat$a),”)
它应该可以工作。tmp[[I]会发出警告(但没有问题)]==tmp[[i-1]]比较,因为它们有时长度不同。好的,编辑以修复该问题和长度不匹配警告,该警告适用于此特定数据,但一般不适用。现在应该可以了。
df <- data.frame(A=c("xxx", "xxx", "xxx1", "xx1x", "yyyy", "gggg"))
f <- function(x){
x <- as.vector(x)
same <- sapply(seq(length(x)-1),
function(i)any(agrep(x[i+1], x[1], max.distance=0.25)))
ex <- embed(x, 2)
c(x[1], ifelse(same, ex[, 2], ex[, 1]))
}
df$B <- f(df$A)
df
A B
1 xxx xxx
2 xxx xxx
3 xxx1 xxx
4 xx1x xxx1
5 yyyy yyyy
6 gggg gggg
dat <- data.frame(A=c('xxx','xxx','xxx1','xx1x','yyyy','gggg'))
dat$B <- rep(NA,nrow(dat))
tmp <- strsplit(as.character(dat$A),"")
dat$B[1] <- dat$A[1]
for (i in 2:length(tmp)){
n <- min(length(tmp[[i]]),length(tmp[[i-1]]))
x <- sum(tmp[[i]][1:n] == tmp[[i-1]][1:n]) / length(tmp[[i]])
if (x >= 0.75){
dat$B[i] <- paste(tmp[[i-1]],collapse="")
}
else{ dat$B[i] <- paste(tmp[[i]],collapse="")}
}