我是R的新手,并试图了解如何在R中实现以下算法。 我有两个字符列表,想看看这两个字符之间的最小距离是多少。
List 1: "a", "b", "c"
List 2: "a", "b", "c", "d"
第一步: 我创建了一个这样的表:
a b c
a 0 1 2
b 1
c 2
d 3
第二步:我用0填充矩阵的其余部分
a b c
a 0 1 2
b 1 0 0
c 2 0 0
d 3 0 0
现在,我要开始使用此算法计算这两个列表之间的距离并更新矩阵:
if (characters_in_header_of_matrix[i]==characters_in_column_of_matrix [j] & value[i,j] == value[i+1][j-1] )
then {get the 'diagonal value' #diagonal value= value[i, j-1]}
else{
value[i,j] = min(value[i-1, j], value[i-1, j-1], value[i, j-1]) + 1
}
endif
为了找到您可以在矩阵的标题和列中看到的两个列表之间的差异,我使用了strcmp()
函数。但是,我无法实现这一点。
最终结果应如下所示:
a b c
a 0 1 2
b 1 0 1
c 2 1 0
d 3 2 1
感谢您的帮助。谢谢
答案 0 :(得分:2)
在R中,您可以 使用for
循环和条件进行暴力破解,但可以通过向量化方法轻松完成。好处可能是速度(尽管可能不是),但通常可以通过更简单的代码来理解,并且(一旦您可以使用这些功能)就可以提高可读性和可维护性。
以这个问题为例
l1 <- c("a", "b", "c")
l2 <- c("a", "b", "c", "d")
您要查找l1
中每个字母与l2
中每个字母之间的“距离”(即绝对距离)。 outer
函数执行两个向量的"outer product"。例如,如果我们要建设性地(而不是实际地)进行outer(a:c, 1:3)
,它将配对a1
,a2
,a3
,b1
,..., c3
。 (那不是合法的R代码,只是用于演示,尽管只需添加少量的附加代码就可以很容易地完成它。)
在我们的案例中,如果执行outer(l1, l2)
,则它使用的函数默认为乘法(*
),因为它的初始用法通常是线性代数,但是可以很容易地用{覆盖{1}}。在内部,它正在做的是创建两个(更长)的向量来完成所有配对。如果引入调试功能来检查状态,我们可以看到幕后发生的事情。
FUN=
(debugfunc <- function(a, b) { browser(); 1; }
仅作为占位符。)
1
依次将outer(l1, l2, FUN=debugfunc)
# Called from: FUN(X, Y, ...)
# Browse[2]>
a # <--- the object 'a' here is the first argument to this function
# [1] "a" "b" "c" "a" "b" "c" "a" "b" "c" "a" "b" "c"
# Browse[2]>
b # <--- the second argument
# [1] "a" "a" "a" "b" "b" "b" "c" "c" "c" "d" "d" "d"
与"a"
,然后将"a"
与"b"
,然后将"a"
与"c"
配对,以此类推。第一个("a"
)向量,然后递增第二个向量,重复直到两个向量都用尽。此时,l1
被这两个向量精确地调用了一次(有些人可能怀疑不是每对一次),因此您的debugfunc
函数必须能够在一个调用中完成所有操作。 / p>
可能要看看这里的距离。您可以使用FUN=
确定单个字母在字母表中的位置(同伴match("a", letters)
是全大写字母)。通常,LETTERS
查找第一个自变量在第二个自变量中的位置。因此,继续在match
内:
debugfunc
因此,您真正想要的是这两个数值向量之间的差异。一个人可以轻松做到:
# Browse[2]>
match(a, letters)
# [1] 1 2 3 1 2 3 1 2 3 1 2 3
# Browse[2]>
match(b, letters)
# [1] 1 1 1 2 2 2 3 3 3 4 4 4
但是因为我们需要绝对距离,所以我们确实需要
# Browse[2]>
match(a, letters) - match(b, letters)
# [1] 0 1 2 -1 0 1 -2 -1 0 -3 -2 -1
好,所以我认为我们在这里有功能。让我们跳出调试器(# Browse[2]>
abs( match(a, letters) - match(b, letters) )
# [1] 0 1 2 1 0 1 2 1 0 3 2 1
)并更正式地尝试一下:
Q
请注意,第一个参数成为行,因此长度为3的distfunc <- function(a, b) abs( match(a, letters) - match(b, letters) )
outer(l1, l2, FUN=distfunc)
# [,1] [,2] [,3] [,4]
# [1,] 0 1 2 3
# [2,] 1 0 1 2
# [3,] 2 1 0 1
给我们3行。如果您需要应用行/列名称,则:
l1
(更改参数的顺序将为您提供正要查找的矩阵。)