mutate() 基于另一个列表的列表

mutate() a list based upon another list

在这个例子中,我有两个列表

tiers <- list("tier 1", "tier 2", "tier 3")

main <- list(data.frame(a = c("this", "that")), 
             data.frame(a = c("the other", "that too")), 
             data.frame(a = c("once more", "kilgore trout")))

我想 mutate() main 中的每个列表元素(即 data.frame()),方法是从相应元素中添加 tiers 中的值。我以为 mapply() 会做:

library(dplyr)

mapply(function(x, y) y %>% mutate(tier = x), tiers, main)

但我得到了意想不到的结果

> mapply(function(x, y) y %>% mutate(tier = x), tiers, main)
     [,1]        [,2]        [,3]       
a    factor,2    factor,2    factor,2   
tier Character,2 Character,2 Character

而我的预期是

[[1]]
     a   tier
1 this tier 1
2 that tier 1

[[2]]
          a   tier
1 the other tier 2
2  that too tier 2

[[3]]
              a   tier
1     once more tier 3
2 kilgore trout tier 3

我使用 mapply() 正确吗?如果没有,我应该使用什么来获得我期望的结果?我应该注意,实际数据最多可能有 n 个列表元素;我无法根据 1:n.

对任何值进行硬编码

您需要在 mapply 调用中添加 SIMPLIFY = FALSE

library(dplyr)
mapply(function(x, y) y %>% mutate(tier = x), tiers, main, SIMPLIFY = FALSE)


#     a   tier
#1 this tier 1
#2 that tier 1

#[[2]]
#          a   tier
#1 the other tier 2
#2  that too tier 2

#[[3]]
#              a   tier
#1     once more tier 3
#2 kilgore trout tier 3

?mapply

SIMPLIFY - attempt to reduce the result to a vector, matrix or higher dimensional array;

SIMPLIFY 参数在 mapply 中默认为 TRUE,在 Map

中默认为 FALSE
Map(function(x, y) y %>% mutate(tier = x), tiers, main)

如果您想将所有内容都保留在基数 R 中,您可以使用 cbind

Map(cbind, main, tiers)

此外,考虑 withintransformMap(将版本包装器列表到 mapply)并避免为一个功能加载包,mutate :

Map(function(x, y) within(y, tier <- x), tiers, main)

Map(function(x, y) transform(y, tier = x), tiers, main)

我们可以在 tidyverse 中使用 map2

library(tidyverse)
map2(main, tiers, ~ .x %>%
           mutate(tiers = .y))
#[[1]]
#     a  tiers
#1 this tier 1
#2 that tier 1

#[[2]]
#          a  tiers
#1 the other tier 2
#2  that too tier 2

#[[3]]
#              a  tiers
#1     once more tier 3
#2 kilgore trout tier 3

在基础 R 中,您可以将 Map 与函数 data.frame 一起使用,如果您将 tier 参数命名为 :

Map(data.frame, main, tier=tiers)
# [[1]]
#      a   tier
# 1 this tier 1
# 2 that tier 1
# 
# [[2]]
#           a   tier
# 1 the other tier 2
# 2  that too tier 2
# 
# [[3]]
#               a   tier
# 1     once more tier 3
# 2 kilgore trout tier 3