使用purrr :: map从列表中提取时出现意外行为

时间:2017-09-01 16:28:04

标签: r purrr

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

<form>
...
<div class="submit-button">
  <input class="form-submit" type="submit" id="edit-submit-fda-views" name="" value="Submit">    
</div>
<div class="reset-button">
  <input type="submit" id="edit-reset" name="op" value="Reset Filters" class="form-submit">      
</div>
...
</form>

这也有效:

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

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

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

> [[1]]
> NULL

> [[2]]
> NULL

> [[3]]
> NULL

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

因为我们知道'物种'的位置,所以应该有效

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

但我得到同样的回应。

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

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

上下文是我正在处理一个混合的引导结果列表,其中我想要的元素位于具有不同名称和结构的大型列表中。我一直在尝试访问'list of list'组件但是我一直从map()获得'Null'。

2 个答案:

答案 0 :(得分:2)

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

来自文档:

  

modify_depth(x,0,fun)相当于x []&lt; - fun(x)
  modify_depth(x,1,fun)相当于x []&lt; - map(x,fun)
  modify_depth(x,2,fun)相当于x []&lt; - map(x,~map(。,fun))

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

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

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

您可以使用

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

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

答案 1 :(得分:1)

首先通过查看来获取数据。我使用了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

enter image description here

有时候看一下数据很好。

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

使用矢量化索引首先为“花朵”组合子集。列表,然后转到&#39; iris1&#39;,然后&#39;物种&#39;。如上所述,您可以使用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级,然后提取物种&#39; < / H2>
aNamedList[1] %>% modify_depth(2, "Species")