3
> 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由于回收而损坏。

我可以用 写ifelseif...else但效率很低。常见的处理方法是什么?

4

4 回答 4

3

此解决方案产生正确答案:

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,因此与显式循环相比,这应该非常快。

于 2013-11-04T12:14:06.330 回答
2
b[b == 0] <- NA
ifelse(is.na(b), 5, a[b])
于 2013-11-04T18:08:10.883 回答
2

没有将效率与保罗的答案进行比较,但是为了您考虑这种(也许)特殊情况:

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,这种方法很可能不起作用。

于 2013-11-04T12:53:46.327 回答
0

之前的两个答案都使用了a[_conditions_]而不是,_conditions_(a[])这似乎更适合您的情况;这个答案也有相同的概念:)。

除了提到的其他方法之外,一种方法是使用 likea[ifelse(, , b)]和 not ifelse(, , a[b])。我能想出的唯一解决方案是在末尾放大aa ,所以可以使用类似的东西;当然,必须在上述调用之前重新分配。5a[ifelse(b == 0, which(a == 5), b)]a

只是为了避免更改并避免在您工作的环境中a分配额外的变量(即备份),您可以将所有内容包装在; 否则在答案中看起来很酷并且可以避免:alocallocal

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(, , )]. 另外,我不确定这是否有任何限制。

我希望我没有错过一些严重的事情。

于 2013-11-04T18:02:51.523 回答