Создайте столбец входных элементов с помощью purrr :: map_df, используя .id, не дублируя входные данные для именованного вектора - PullRequest
0 голосов
/ 15 ноября 2018

Я часто хочу отобразить вектор имен столбцов во фрейме данных и отслеживать вывод, используя аргумент .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 

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Вот альтернативное решение для вашего конкретного сценария, использующее 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 из-за ожидаемого поведения, которое вы указали в своем вопросе. Тем не менее, вы можете использовать оболочку «случай змеи» для 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
0 голосов
/ 15 ноября 2018

Вы можете легко создать свой входной вектор с помощью:

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...