R中的map函数让你感到困惑了吗?

4

我使用purrr库在R中编写了以下内容。起初有点复杂,但经过20次尝试,我将其简化到基础部分以查看发生了什么。

map(list(1:60), function(a) { 
    if (a < 2) {
        return(1)
    } else {
        return(0)
    }})

[[1]]
[1] 1

警告信息: 在 if (a < 2) { 中:

条件长度大于1,只有第一个元素将被使用

期望的结果是一个列表,其中第一个和第二个元素的值都为1,其余元素的值为0。

发生了什么?


我不知道为什么在“列表”中有“1:60”,但是+(1:60<2)会给您相同的输出。 - Ronak Shah
1个回答

6
如果我们把它放在list里,它将被视为一个单元。
library(purrr)
map(1:60, ~ if(.x > 2) 1 else 0)

请注意,在tidyverse中,~是匿名函数调用的一种简洁方式(function(x) if(x > 2) 1 else 0)。

或者如果我们正在创建包含60个元素的list,那么as.list会非常有用。

map(as.list(1:60), ~ if(.x > 2) 1 else 0)

为此,我们不需要循环,因为可以使用“unlist”并仅使用2进行比较(>),以创建逻辑向量,该向量可以通过as.integer转换为二进制或(+ -将TRUE-> 1,FALSE-> 0)
+(unlist(as.list(1:60)) > 2)

如果输出需要是一个列表,则使用as.list进行包装。

as.list(+(unlist(as.list(1:60)) > 2))

在楼主的代码中,发生了什么事情是这样的:
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

输入是一个只有单个元素的列表,该元素具有长度为60。使用map对该单个元素进行循环,但if/else不是矢量化的。

根据?Control,使用方法如下:

if(cond) cons.expr else alt.expr

其中

cond - 长度为1且不为NA的逻辑向量。长度大于1的条件目前被接受并带有警告,但仅使用第一个元素。当环境变量为时,会发出错误信号

这导致warning消息,即if/else预计list元素只有length为1。相反,我们可以使用矢量化的ifelse

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

或者只提取list元素。
ifelse(list(1:60)[[1]] > 2, 1, 0)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接