> a <- factor(1:3)
> b <- c(0,1,2)
> ifelse(b == 0, 5, a[b])
[1] 5 2 1
我希望看到5,1,2
原因是a[b]
实际返回1, 2
的 ,其长度与 不同a
,因此结果ifelse
由于回收而损坏。
我可以用 写ifelse
,if...else
但效率很低。常见的处理方法是什么?
> a <- factor(1:3)
> b <- c(0,1,2)
> ifelse(b == 0, 5, a[b])
[1] 5 2 1
我希望看到5,1,2
原因是a[b]
实际返回1, 2
的 ,其长度与 不同a
,因此结果ifelse
由于回收而损坏。
我可以用 写ifelse
,if...else
但效率很低。常见的处理方法是什么?
此解决方案产生正确答案:
a <- factor(1:3)
b <- c(0,1,2)
a = as.numeric(a)
zero_logical = b != 0 # Precompute because if a contains a zero, this will also be replaced by 5
b[zero_logical] <- a[b[zero_logical]]
b[!zero_logical] <- 5
b
[1] 5 1 2
此解决方案使用两个分配,一个 forb != 0
和一个 for b == 0
,因此与显式循环相比,这应该非常快。
b[b == 0] <- NA
ifelse(is.na(b), 5, a[b])
没有将效率与保罗的答案进行比较,但是为了您考虑这种(也许)特殊情况:
a <- factor(1:3)
b <- c(0,1,2)
a2 <- as.factor(c("5", a))
a2[b + 1]
# [1] 5 1 2
# Levels: 1 2 3 5
如果您正在寻找 以外的任何东西b == 0
,这种方法很可能不起作用。
之前的两个答案都使用了a[_conditions_]
而不是,_conditions_(a[])
这似乎更适合您的情况;这个答案也有相同的概念:)。
除了提到的其他方法之外,一种方法是使用 likea[ifelse(, , b)]
和 not ifelse(, , a[b])
。我能想出的唯一解决方案是在末尾放大a
a ,所以可以使用类似的东西;当然,必须在上述调用之前重新分配。5
a[ifelse(b == 0, which(a == 5), b)]
a
只是为了避免更改并避免在您工作的环境中a
分配额外的变量(即备份),您可以将所有内容包装在; 否则在答案中看起来很酷并且可以避免:a
local
local
a <- factor(1:3)
b <- c(0,1,2)
res <- local({ # just to keep all environments clean and to not re-assign `a`
a = as.numeric(as.character(a))
a[length(a) + 1] <- 5
a[ifelse(b == 0, which(a == 5), b)]
})
res
#[1] 5 1 2
a
#[1] 1 2 3 #not changed `a`
#Levels: 1 2 3
我想不出更优雅的方式来使用a[ifelse(, , )]
. 另外,我不确定这是否有任何限制。
我希望我没有错过一些严重的事情。