R中的矢量化IF语句?

Chr*_*ian 35 if-statement r vectorization

x <- seq(0.1,10,0.1)
y <- if (x < 5) 1 else 2
Run Code Online (Sandbox Code Playgroud)

我希望if能够对每一个案例进行操作,而不是对整个向量进行操作.我需要改变什么?

Rom*_*rik 54

x <- seq(0.1,10,0.1)

> x
  [1]  0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1.0  1.1  1.2  1.3  1.4  1.5
 [16]  1.6  1.7  1.8  1.9  2.0  2.1  2.2  2.3  2.4  2.5  2.6  2.7  2.8  2.9  3.0
 [31]  3.1  3.2  3.3  3.4  3.5  3.6  3.7  3.8  3.9  4.0  4.1  4.2  4.3  4.4  4.5
 [46]  4.6  4.7  4.8  4.9  5.0  5.1  5.2  5.3  5.4  5.5  5.6  5.7  5.8  5.9  6.0
 [61]  6.1  6.2  6.3  6.4  6.5  6.6  6.7  6.8  6.9  7.0  7.1  7.2  7.3  7.4  7.5
 [76]  7.6  7.7  7.8  7.9  8.0  8.1  8.2  8.3  8.4  8.5  8.6  8.7  8.8  8.9  9.0
 [91]  9.1  9.2  9.3  9.4  9.5  9.6  9.7  9.8  9.9 10.0

> ifelse(x < 5, 1, 2)
  [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 [38] 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 [75] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
Run Code Online (Sandbox Code Playgroud)

  • 这对于仅替换某些值也非常有用:例如`x = ...; x [x <5] = 1`是`ifelse(x <5,1,x)` (2认同)
  • @skan尝试`y [x &lt;5]`。假设x和y的长度相同 (2认同)

Jor*_*eys 12

为了完整性:在大向量中,您可以使用索引来加快速度(我们通常在模拟中执行此操作,其中函数通常运行1000到10000次).但只要没有必要,只需使用即可ifelse.这读起来容易多了.

> set.seed(100)
> x <- runif(1000,1,10)

> system.time(replicate(10000,{
+     y <- ifelse(x < 5,1,2)
+ }))
   user  system elapsed 
   2.56    0.08    2.64 

> system.time(replicate(10000,{
+   y <- rep(2,length(x))
+   y[x < 5]<- 1
+ }))
   user  system elapsed 
   0.48    0.00    0.48 
Run Code Online (Sandbox Code Playgroud)

  • 小心 - 如果`x`包含`NA`元素(在第一个中将保持为"NA",但在第二个中将被分配为"1"),则您的两个示例不等效. (6认同)
  • 你可以进一步削减时间.我的机器在0.436中执行了第二种方法(虽然在第一种方法上速度较慢),但这又提高了200%:system.time(复制(10000,{y < - (y <5)+ 2*!( y <5)}))用户系统经过0.101 0.021 0.128 (3认同)

Jos*_*ich 11

y <- if (x < 5) 1 else 2不对整个向量进行操作(您收到的警告只会告诉您将使用该条件的第一个元素).你想要ifelse:

y <- ifelse(x < 5, 1, 2)
Run Code Online (Sandbox Code Playgroud)

ifelse对整个逻辑向量进行逐元素操作. if只接受一个逻辑值.见?"if"?ifelse