将两个向量逐个元素相结合

8

I have 2 vectors, such as these:

A <- c(1,2,NA,NA,NA,NA,7)
B <- c(NA,NA,3,4,NA,NA,7)

我希望将它们结合起来,以便得到结果向量。
1,2,3,4,NA,NA,-1

这是这样的

  1. 当一个向量在位置i上只有一个值(比如X),另一个值为NA时,新的向量应该在位置i处取X的值。

  2. 当两个向量在位置i上都是NA时,新的向量应该在位置i处取NA的值。

  3. 当两个向量在位置i上都有一个值时,新的向量应该在位置i处取-1的值。

我可以很容易地用循环来实现,但对于大型数据集来说速度非常慢,所以有人能提供一种快速的方法吗?


迭代似乎是你唯一的希望。缓慢可能是由于分支预测问题引起的。 - AJMansfield
你认为什么样的数据集算是大型数据集? - Roland
3个回答

11

这些命令创建向量:

X <- A
X[is.na(A)] <- B[is.na(A)]
X[is.na(B)] <- A[is.na(B)]
X[!is.na(A & B)] <- -1

#[1]  1  2  3  4 NA NA -1

这就是我要说的...我得更早地起床! - Carl Witthoft
1
如果你在开始时执行 X <- -A^0 来创建一个带有-1的向量,那么你就不需要最后一行代码了,整个过程会更快。 - Roland
有趣的是,@Roland:原来 X <- -A^0X<- rep(-1,length(A)) 更快。 - Carl Witthoft
@Carl Witthoft 是的,如果您需要优化代码,那是一个方便的技巧。 - Roland

5
A <- c(1,2,NA,NA,NA,NA,7)
B <- c(NA,NA,3,4,NA,NA,7)
C <- rowMeans(cbind(A,B),na.rm=TRUE)
C[which(!is.na(A*B))]<- -1
#[1]   1   2   3   4 NaN NaN  -1

基准测试:

Unit: microseconds
          expr    min     lq median     uq     max
1 Roland(A, B) 17.863 19.095 19.710 20.019  68.985
2   Sven(A, B) 11.703 13.243 14.167 14.783 100.398

除了 NaN 不同于 NA 之外,你应该添加一行代码将 NaN 替换为 NA。 - Carl Witthoft
如果这很重要的话,做起来很容易。然而,Sven的解决方案无论如何都更高效。 - Roland
这种解决方案的一个优点是,如果存在两个值,则提供平均值。在某些情况下,这可能很有用。 - JASC

2
有点晚了,但这里有另一种选项,定义一个函数通过对两个 cbind 在一起的向量应用规则来实现。
# get the data
A <- c(1,2,NA,NA,NA,NA,7)
B <- c(NA,NA,3,4,NA,NA,7)

# define the function
process <- function(A,B) {
  x <- cbind(A,B)
  apply(x,1,function(x) {
    if(sum(is.na(x))==1) {na.omit(x)} else
    if(all(is.na(x))) {NA} else
    if(!any(is.na(x))) {-1}
  })
}

# call the function
process(A,B)
#[1]  1  2  3  4 NA NA -1

使用函数的主要优点是更容易更新规则或输入,以将代码应用于新数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接