我的df有以下条目:
A
xxx
xxx
xxx1
xx1x
yyyy
gggg
Run Code Online (Sandbox Code Playgroud)
我想根据以下条件,根据A列的相似性将符号添加到我的df的B列.
我将阈值设置为=或> 75%相似.
A列已经排序.因此,需要检查上述ONE的相似性.
如果上面一个相似,则符号将从上面的列B中复制.
如果上面的不相似,则符号将从同一行的列A中复制.
例如,第1行和第2行是相同的.它们的符号与A列相同.第3行是(4个字母中的3个字母具有相同的字母且序列相同)75%与row1和row2相似.B列中的sybmol将从上面复制,即xxx.由于xx1x(row4)只有4个字母中的2个类似于row3,因此它只使用自己的符号,即xx1x.由于yyyy和gggg完全不同,他们将保留自己的sybmol,如A列.
因此,我的最终结果应该是这样的:
A B
xxx xxx
xxx xxx
xxx1 xxx
xx1x xx1x
yyyy yyyy
gggg gggg
Run Code Online (Sandbox Code Playgroud)
我通过猜测得出这个相似度(如果有正式的字符串相似性搜索方法则不需要使用),如果有任何形式的方法来检查R中的字符串相似性,那么它可能很好用.
您能介意如何使用R有效地添加此符号列吗?
设置数据:
x=c("xxx", "xxx", "xxx1", "xx1x", "yyyy", "gggg")
Run Code Online (Sandbox Code Playgroud)
代码:
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])))
Run Code Online (Sandbox Code Playgroud)
结果:
A B
[1,] "xxx" "xxx"
[2,] "xxx" "xxx"
[3,] "xxx1" "xxx"
[4,] "xx1x" "xxx1"
[5,] "yyyy" "yyyy"
[6,] "gggg" "gggg"
Run Code Online (Sandbox Code Playgroud)
它为什么有效?
一些关键概念和非常有用的功能:
首先,使用agrep它来测试类似字符串的类型Levenshtein edit distance,它有效地计算将一个字符串转换为另一个字符串所需的单个字符更改的数量.该参数max.distance=0.25意味着允许25%的模式字符串不同.
例如,测试任何原始字符串是否与"xxx"类似:返回1:4:
agrep("xxx", x, max.distance=0.25)
[1] 1 2 3 4
Run Code Online (Sandbox Code Playgroud)
其次,embed提供了一种测试滞后变量的有用方法.例如,embed(x, 2) turnsx`成为滞后数组.这使得比较x [1]和x [2]变得容易,因为它们现在位于数组中的同一行:
embed(x, 2)
[,1] [,2]
[1,] "xxx" "xxx"
[2,] "xxx1" "xxx"
[3,] "xx1x" "xxx1"
[4,] "yyyy" "xx1x"
[5,] "gggg" "yyyy"
Run Code Online (Sandbox Code Playgroud)
最后,我使用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
Run Code Online (Sandbox Code Playgroud)