我经常想映射数据框中列名称的向量,并使用.id
参数跟踪输出。但是,要将与每个map
迭代相关的列名称写入该.id
列,似乎需要在输入向量中将它们的名称加倍-换句话说,通过用自己的名称命名每个列名称。如果我没有使用自己的名称来命名列,那么.id
仅存储迭代的索引。
根据purrr::map docs,这是预期的行为:
.id
字符串或NULL。如果是字符串,则输出将包含具有该名称的变量,该变量存储输入的名称(如果已命名.x)或索引(如果未命名.x)。
但是我的方法有点笨拙,所以我想我缺少了一些东西。有没有更好的方法来获取要迭代的列的列表,而又不需要在输入向量中每次写两次列名?任何建议将不胜感激!
下面是一个可以使用的示例:
library(rlang)
library(tidyverse)
tb <- tibble(foo = rnorm(10), bar = rnorm(10))
cols_once <- c("foo", "bar")
cols_once %>% map_dfr(~ tb %>% summarise(avg = mean(!!sym(.x))), .id="var")
# A tibble: 2 x 2
var avg <-- var stores only the iteration index
<chr> <dbl>
1 1 -0.0519
2 2 0.204
cols_twice <- c("foo" = "foo", "bar" = "bar")
cols_twice %>% map_dfr(~ tb %>% summarise(avg = mean(!!sym(.x))), .id="var")
# A tibble: 2 x 2
var avg <-- var stores the column names
<chr> <dbl>
1 foo -0.0519
2 bar 0.204
答案 0 :(得分:3)
这是使用summarize_at
和gather
针对您的特定情况的替代解决方案:
tb %>% summarize_at( cols_once, mean ) %>% gather( var, avg )
# # A tibble: 2 x 2
# var avg
# <chr> <dbl>
# 1 foo 0.374
# 2 bar 0.0397
在更一般的情况下,由于您在问题中指出了预期的行为,因此我认为在使用cols_once
时没有办法命名map_dfr
。但是,您可以将{snake case“包装器用于setNames()
,以使其更加美观:
cols_once %>% set_names %>%
map_dfr(~ tb %>% summarise(avg = mean(!!sym(.x))), .id="var")
# # A tibble: 2 x 2
# var avg
# <chr> <dbl>
# 1 foo 0.374
# 2 bar 0.0397
答案 1 :(得分:1)
您可以使用以下方法轻松创建输入向量:
setNames(names(tb), names(tb))
因此您的代码应为:
setNames(names(tb), names(tb)) %>%
map_dfr(~ tb %>% summarise(avg = mean(!!sym(.x))), .id="var")
根据您的评论进行编辑:
仍然不是您想要的解决方案,但是当您不使用所有列名时,仍然可以使用setNames()
并将所需的子集进行子集化(或将不需要的子集化出)
tb <- tibble(foo = rnorm(10), bar = rnorm(10), taz = rnorm(10))
setNames(names(tb), names(tb))[-3]