我用 purrr 库在 R 中编写了以下内容。好吧,它开始变得更加复杂,但是在尝试了 20 次之后,我将其简化为基本知识,以了解发生了什么。
map(list(1:60), function(a) {
if (a < 2) {
return(1)
} else {
return(0)
}})
Run Code Online (Sandbox Code Playgroud)
[[1]]
[1] 1
Run Code Online (Sandbox Code Playgroud)
警告消息:在 if (a < 2) { 中:
条件的长度 > 1 并且只使用第一个元素
预期结果是一个列表,其中前两个元素的值是 1,其余元素的值是 0。
这里发生了什么?
If we place it in a list, it would be treated as a single unit
library(purrr)
map(1:60, ~ if(.x > 2) 1 else 0)
Run Code Online (Sandbox Code Playgroud)
Note that the ~ is a compact way in tidyverse for anonymous function call (function(x) if(x > 2) 1 else 0)
Or if we are creating a list of 60 elements, then as.list would be useful
map(as.list(1:60), ~ if(.x > 2) 1 else 0)
Run Code Online (Sandbox Code Playgroud)
For this, we don't need a loop though, as it can be unlistted and simply do a comparison (>) with 2 to create a logical vector which can be coerced to binary with as.integer or (+ - converts the TRUE -> 1, FALSE -> 0)
+(unlist(as.list(1:60)) > 2)
Run Code Online (Sandbox Code Playgroud)
and if the output needs to be a list, wrap with as.list
as.list(+(unlist(as.list(1:60)) > 2))
Run Code Online (Sandbox Code Playgroud)
In the OP's code, what happened is
list(1:60)
#[[1]]
#[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#[43] 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
Run Code Online (Sandbox Code Playgroud)
the input is a list with only single element having a length of 60. With map, it loops through that single element, but if/else is not vectorized
According to ?Control, the usage is
if(cond) cons.expr else alt.expr
where
cond - A length-one logical vector that is not NA. Conditions of length greater than one are currently accepted with a warning, but only the first element is used. An error is signalled instead when the environment variable
and this results in the warning message i.e. if/else expects the list element to have a length of just 1. Instead, we can use ifelse which is vectorized
map(list(1:60), ~ ifelse(.x > 2, 1, 0))
#[[1]]
#[1] 0 0 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 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Run Code Online (Sandbox Code Playgroud)
Or just extract the list element
ifelse(list(1:60)[[1]] > 2, 1, 0)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
223 次 |
| 最近记录: |