0

我有一个与此类似的问题 - 2 个逻辑向量(取 2)的元素之间的快速最小距离(间隔), 但它有一些重要的区别。

假设我有一个向量:

x <- c("A", "B", "C", "A", "D", "D", "A", "B", "A")

我想做的是:

对于每个元素,仅计算它与每个不同类型的下一个元素之间的最小距离。如果对于任何元素,在前向方向上没有出现特定类型的元素,则应返回 0。返回的数据将如下所示:

所需的输出表-

N  x  A  B  C  D
1  A  3  1  2  4
2  B  2  6  1  3
3  C  1  5  0  2
4  A  3  4  0  1
5  D  2  3  0  1
6  D  1  2  0  0
7  A  2  1  0  0
8  B  1  0  0  0
9  A  0  0  0  0

第一列/var 只是指元素顺序。第二个 col/var 是该位置的元素。然后有四个 cols/vars - 每个都是出现在向量中的唯一元素。

这四个 cols/vars 中的每一个中的数字都是从该行的元素到仅在 FORWARD 方向上每种类型的下一个出现的元素的最小距离。如果输入“0”,则表示该元素不会出现在向量中该行的元素之后。

如何做到这一点?

我的第一个想法是尝试模仿上述问题的某些方面。为此,我使用 grepl 函数将向量转换为四个独立的逻辑向量,指示每个元素的存在/不存在。

xA<-grepl("A", x) #  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE
xB<-grepl("B", x) #  FALSE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
xC<-grepl("B", x) #  FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
xD<-grepl("D", x) #  FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE

然后我尝试了“Flodel”函数和 GG 使用 library(data.table) 提供的第二个函数。

例如,要计算从所有“As”到“D”的最小距离:

flodel <- function(x, y) {
  xw <- which(x)
  yw <- which(y)
  i <- findInterval(xw, yw, all.inside = TRUE)
  pmin(abs(xw - yw[i]), abs(xw - yw[i+1L]), na.rm = TRUE)
}
flodel(xA,xD)

> [1] 4 1 1 3




#GG's data.table option
wxA <- data.table(x = which(xA))
wxD <- data.table(y = which(xD), key = "y")
wxD[wxA, abs(x - y), roll = "nearest"] 

#   y V1
#1: 1  4
#2: 4  1
#3: 7  1
#4: 9  3

这两个选项都找到了所有 A 到 D 的最小距离。但是,它是在任何方向上,而不仅仅是 FORWARD 方向。GG 的 data.table 选项在表面上对我更有吸引力,因为它返回的数据显示了每个元素的位置(输出的 'y' 列),这可以很容易地打包成一个漂亮的汇总表(比如我想要的)上面的输出表)。

我试图找出在 data.table 中使用“roll”参数的替代方法,但我似乎没有解决这个问题。

感谢您的任何建议。

4

2 回答 2

4

另一种似乎有效的方式:

levs = sort(unique(x))
do.call(rbind, 
        lapply(seq_along(x),
               function(n) 
                  match(levs, x[-seq_len(n)], 0)))
#      [,1] [,2] [,3] [,4]
# [1,]    3    1    2    4
# [2,]    2    6    1    3
# [3,]    1    5    0    2
# [4,]    3    4    0    1
# [5,]    2    3    0    1
# [6,]    1    2    0    0
# [7,]    2    1    0    0
# [8,]    1    0    0    0
# [9,]    0    0    0    0
于 2014-07-05T11:10:15.027 回答
1

我不确定这有多有效,但它似乎有效。怎么样

x <- c("A", "B", "C", "A", "D", "D", "A", "B", "A")

#find indexes for each value
locations<-split(seq_along(x), x)

#for each index, find the distance from the next highest 
# index in the locations list
t(sapply(seq_along(x), function(i) sapply(locations, function(l) 
    if(length(z<-l[l>i])>0) z[1]-i else 0)))

这将返回

      A B C D
 [1,] 3 1 2 4
 [2,] 2 6 1 3
 [3,] 1 5 0 2
 [4,] 3 4 0 1
 [5,] 2 3 0 1
 [6,] 1 2 0 0
 [7,] 2 1 0 0
 [8,] 1 0 0 0
 [9,] 0 0 0 0
于 2014-07-05T04:42:59.953 回答