这一定很容易,但我似乎无法使其发挥作用。我有两个长度不等的命名向量:
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
但这让我得到了算术,但没有保留结构。
答案 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
这假定x
和y
的名称顺序相同。
或者,您可以执行类似的操作,但不需要相同的顺序:
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
另一位使用merge
和colSums
colSums(merge(as.list(x), as.list(y), all=T), na.rm=T)
# A D B C
# 12 32 10 15