如何在R中添加不等长的命名向量

时间:2015-07-20 22:24:00

标签: r vector

这一定很容易,但我似乎无法使其发挥作用。我有两个长度不等的命名向量:

x <- as.vector(c(5, 10,15,20))
names(x) <- c("A", "B", "C", "D")
y <- as.vector(c(7, 12))
names(y) <- c("A", "D")

我想添加它们并保留最长的命名约定。我希望x + y能够产生:

A   B   C   D
12  10  15  32

我已经尝试使长度与其他地方建议的相等,并允许算术,但不保留命名约定。我也尝试过这样的事情:

z <- x[names(y)] + y

但这让我得到了算术,但没有保留结构。

3 个答案:

答案 0 :(得分:6)

您可以使用tapply()

z <- c(x, y)
tapply(z, names(z), sum)
#  A  B  C  D 
# 12 10 15 32 

答案 1 :(得分:2)

您可以使用replace执行此操作,匹配两个向量的名称:

x + replace(rep(0, length(x)), names(x) %in% names(y), y)
#  A  B  C  D 
# 12 10 15 32 

这假定xy的名称顺序相同。

或者,您可以执行类似的操作,但不需要相同的顺序:

z <- x
m <- match(names(y), names(x))
z[m] <- z[m] + y
z
#  A  B  C  D 
# 12 10 15 32 

虽然这些都不像@ RichardScriven建议使用tapply那样简洁,但它们对大型载体的效率都很高:

set.seed(144)
big.x <- runif(1000000)
names(big.x) <- paste("x", 1:1000000)
big.y <- big.x[sort(sample(1:1000000, 500000))]
sum.rscriven <- function(x, y) {
  z <- c(x, y)
  tapply(z, names(z), sum)
}
sum.josilber1 <- function(x, y) x + replace(rep(0, length(x)), names(x) %in% names(y), y)
sum.josilber2 <- function(x, y) {
  z <- x
  m <- match(names(y), names(x))
  z[m] <- z[m] + y
  z
}
system.time(sum.rscriven(big.x, big.y))
#    user  system elapsed 
#  12.650   0.151  12.817 
system.time(sum.josilber1(big.x, big.y))
#    user  system elapsed 
#   0.214   0.002   0.215 
system.time(sum.josilber2(big.x, big.y))
#    user  system elapsed 
#   0.180   0.003   0.182 

请注意,在此示例中,两个建议的解决方案至少比tapply解决方案快50倍(长度为1百万的big.x,长度为500k的big.y),因为它们执行单个解决方案向量化加法而不是对sum的许多小调用。

答案 2 :(得分:1)

一个使用length<-colSums

colSums(rbind(x, `length<-`(y, length(x))[names(x)]), na.rm=T)
#  A  B  C  D 
# 12 10 15 32 

另一位使用mergecolSums

colSums(merge(as.list(x), as.list(y), all=T), na.rm=T)
#  A  D  B  C 
# 12 32 10 15