#r #dplyr #purrr
#r #dplyr #purrr
Вопрос:
Я хотел бы расти foo
, дублируя его n
несколько раз, и различать каждую копию foo
с уникальным значением новой переменной. Если n
равно 3, я могу сделать это подробно с помощью:
library(tidyverse)
foo <- mtcars %>%
filter(row_number() < 3)
# desired result
bind_rows(
foo %>% mutate(key = "a"),
foo %>% mutate(key = "b"),
foo %>% mutate(key = "c")
)
#> mpg cyl disp hp drat wt qsec vs am gear carb key
#> 1 21 6 160 110 3.9 2.620 16.46 0 1 4 4 a
#> 2 21 6 160 110 3.9 2.875 17.02 0 1 4 4 a
#> 3 21 6 160 110 3.9 2.620 16.46 0 1 4 4 b
#> 4 21 6 160 110 3.9 2.875 17.02 0 1 4 4 b
#> 5 21 6 160 110 3.9 2.620 16.46 0 1 4 4 c
#> 6 21 6 160 110 3.9 2.875 17.02 0 1 4 4 c
Я пытаюсь найти более экономный способ сделать это. В идеале я хотел бы поместить решение в одну строку, в которую foo
передается with %>%
.
Моя (неудачная) purrr
попытка:
foo %>%
map_dfr(c("a", "b", "c"), ~ mutate(., key = .x))
Ответ №1:
В вашей попытке использовать purrr
» делание foo %>%
» вам не помогает, потому что вам не нужно foo
быть первым аргументом против map_dfr
. Вместо этого вы можете просто сделать:
map_dfr(c("a", "b", "c"), ~ mutate(foo, key = .x))
Если вы хотите продолжать использовать канал, но перестать foo
передаваться в качестве первого аргумента, вы можете окружить map_dfr
с {}
помощью, которая подавляет автоматическую передачу аргументов:
foo %>%
{ map_dfr(c("a", "b", "c"), function(x) { mutate(., key = x)}) }
(могут быть более элегантные способы сделать это с использованием разных magrittr
каналов, я в основном придерживаюсь %>%
)
Комментарии:
1. Ах. Как-нибудь я могу подавить первый аргумент, чтобы я мог как-то перейти
foo
к этому? В идеале я хотел бы иметь возможность перенести это в канал, в которомfoo
оно модифицируется различными способами до и после выполнения этого.2. Круто, это работает. Должен существовать вариант канала, который не имеет первого аргумента по умолчанию и требует явного размещения точки.
3. @lost «Должен быть вариант канала, который не имеет первого аргумента по умолчанию и требует явного размещения точки». Зачем в этом случае использовать канал? С таким же успехом вы могли бы использовать функцию с явными аргументами функции напрямую. Вся идея конвейера заключается в передаче объекта в LHS в качестве первого аргумента выражения / функции в RHS.
Ответ №2:
Мы можем использовать
library(tidyverse)
set_names(replicate(3, foo, simplify = FALSE), letters[1:3]) %>%
bind_rows(.id = 'key')
Или с помощью uncount
uncount(foo, 3) %>%
mutate(key = rep(letters[1:3], each = 2))
Или с unnest
foo %>%
mutate(key = list(letters[1:3])) %>%
unnest
# mpg cyl disp hp drat wt qsec vs am gear carb key
#1 21 6 160 110 3.9 2.620 16.46 0 1 4 4 a
#2 21 6 160 110 3.9 2.620 16.46 0 1 4 4 b
#3 21 6 160 110 3.9 2.620 16.46 0 1 4 4 c
#4 21 6 160 110 3.9 2.875 17.02 0 1 4 4 a
#5 21 6 160 110 3.9 2.875 17.02 0 1 4 4 b
#6 21 6 160 110 3.9 2.875 17.02 0 1 4 4 c