【问题标题】:unexpected behaviour when extracting from lists with purrr::map使用 purrr::map 从列表中提取时出现意外行为
【发布时间】:2018-02-10 18:26:14
【问题描述】:

我无法理解 purrr::map 的行为方式,例如,这是有效的:

irisList <- list(iris, iris, iris)
carsList <- list(cars, cars, cars)
airqualityList <- list(airquality, airquality, airquality)

irisList %>% map("Species") %>% str(vec.len = 2)

> List of 3 : 
> $ : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 ...  
> $ : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 ...  
> $ : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 ...

carsList %>% map("speed") %>% str(vec.len = 2)

> List of 3
> $ : num [1:50] 4 4 7 7 8 ...
> $ : num [1:50] 4 4 7 7 8 ...
> $ : num [1:50] 4 4 7 7 8 ...

airqualityList %>% map("Ozone") %>% str(vec.len = 2)

> List of 3
> $ : int [1:153] 41 36 12 18 NA ...
> $ : int [1:153] 41 36 12 18 NA ...
> $ : int [1:153] 41 36 12 18 NA ...

这也有效:

mixedList <- list(iris, cars, airquality)

mixedList %>% map("Species") %>% str(vec.len = 2)
> List of 3
> $ : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 ...
> $ : NULL
> $ : NULL

重复但映射“速度”或“臭氧”会给出预期的响应。但是,如果我让它变得更复杂一些,事情就不会像我预期的那样返回:

unNamedList <- list(list(iris, iris, iris),
                list(cars, cars, cars),
                list(airquality, airquality,airquality))
unNamedList %>%  map("Species")

> [[1]]
> NULL

> [[2]]
> NULL

> [[3]]
> NULL

根据 purrr 用户手册,如果我有一个命名列表,我应该能够执行以下操作:

namedIrisList <- list("iris1" = iris,
                      "iris2" = iris,
                      "iris3" = iris)

namedCarsList <- list("cars1" = cars,
                      "cars2" = cars,
                      "cars3" = cars)

namedAirqualityList <- list("aq1" = airquality,
                            "aq2" = airquality,
                            "aq3" = airquality) 

aNamedList <- list("flowers" = namedIrisList,
                   "autos" = namedCarsList,
                   "aq" = namedAirqualityList)

aNamedList %>% map("flowers","Species")

> $flowers
> NULL

> $autos
> NULL

> $aq
> NULL

所以 purrr::map '知道' 'Species' 在哪里,但不返回任何东西。

既然我们知道“物种”的位置,这应该可以工作

 aNamedList %>% map("flowers","iris1","Species")

但我得到了同样的回应。

> $flowers
> NULL

> $autos
> NULL

> $aq
> NULL

我想我不明白应该如何使用 map() 的提取能力。

上下文是我正在处理一个混合的引导结果列表,其中我想要的元素位于具有不同名称和结构的列表的大列表中。我一直在尝试访问“列表列表”组件,但我不断从 map() 中返回“空”。

【问题讨论】:

  • 我使用modify_depth(以前的at_depth)作为列表列表。
  • 另外,aNamedList %&gt;% map("iris1", "Species") 有效(不使用顶级列表的名称,因为这些是 map 循环遍历的列表)。

标签: r purrr


【解决方案1】:

您可以使用modify_depth 从列表列表中提取所需的向量。您指定depth,即您要使用的列表级别。在您的示例中,您正在处理二级列表。

来自文档:

modify_depth(x, 0, fun) 等价于 x[] modify_depth(x, 1, fun) 等价于 x[] modify_depth(x, 2, fun) 等价于 x[]

因此,此代码为嵌套列表的每个元素返回 NULLSpecies 列:

aNamedList %>% modify_depth(2, "Species")

对于嵌套列表的单个元素(如iris1),您可以像以前一样使用名称。但是,顶级列表是您正在循环的内容,因此您不会引用这些名称。例如,当您检查时,names(aNamedList[[1]]) 返回 "iris1" "iris2" "iris3" 而不是 "flowers"

你可以使用

aNamedList %&gt;% map("iris1", "Species")

获取名为iris1 的任何嵌套列表的Species 列。

【讨论】:

    【解决方案2】:

    首先通过查看获取您的数据。我使用listviewerstr 的组合。

    listviewer::jsonedit(aNamedList) # interactive viewer
    str(aNamedList, list.len = 10, max.level = 2) # play with list.len and max.level to adjust visible data
    

    有时只看一组数据很不错。

    str(aNamedList[1]) # subset by 2 or 3 to get autos and aq
    str(aNamedList['flowers']) # this also works with 'autos' and 'aq'
    

    使用矢量化索引首先对“花”列表进行子集化,然后转到“iris1”,然后转到“物种”。像上面一样,你可以用 chr 字符串的 int 子集

    a <- map(aNamedList[1], c(1,5)) # all species from iris1
    b <- map(aNamedList['flowers'], c('iris1', 'Species')) # identical to the line above
    identical(a,b) # returns TRUE
    

    如果我们想要花下所有列表中的所有物种(iris1、iris2、iris3 ...)怎么办

    1。 @aosmith 的解决方案非常好:

    aNamedList %>% modify_depth(2, "Species")
    

    2。假设您只想要花朵信息(而不是其他列表中的空信息),您可以先将 aNamedList 子集设置为仅包含花朵,然后跳转到第 2 级,并提取“物种”

    aNamedList[1] %>% modify_depth(2, "Species")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 1970-01-01
      • 1970-01-01
      • 2018-02-13
      • 1970-01-01
      • 2022-01-02
      相关资源
      最近更新 更多