#r #purrr
#r #purrr
Вопрос:
Я хочу использовать map для применения функции к каждому столбцу tibble. Однако я не хочу, чтобы столбцы tibble были упрощены. Я мог бы справиться с этим, воссоздав tibbles с использованием одного столбца imap
. Однако, как мне это сделать?
Давайте воспользуемся суперпростой функцией, вызываемой test
, чтобы посмотреть, работает ли она.
Поведение по умолчанию: столбцы упрощены до векторов:
test<-function(data){
data
}
tibble(v1=1:20,v2=100:119) %>% map(test)
$v1
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
$v2
[1] 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
Это не может работать, потому что имена должны быть заключены в кавычки:
tibble(v1=1:20,v2=100:119) %>% imap(~test(tibble(.y=.x))) %>% str
List of 2
$ v1: tibble [20 x 1] (S3: tbl_df/tbl/data.frame)
..$ .y: int [1:20] 1 2 3 4 5 6 7 8 9 10 ...
$ v2: tibble [20 x 1] (S3: tbl_df/tbl/data.frame)
..$ .y: int [1:20] 100 101 102 103 104 105 106 107 108 109 ...
Так почему это не работает?
tibble(v1=1:20,v2=100:119) %>% imap(~test(tibble(!!!(.y)=.x)))
Error: unexpected '=' in "tibble(v1=1:20,v2=100:119) %>% imap(~test(tibble(!!!(.y)="
Ответ №1:
Мы можем изменить оператор =
присваивания на ( :=
) и вычислить ( !!
) значение .
y в lhs :=
library(tibble)
library(purrr)
out <- tibble(v1=1:20,v2=100:119) %>%
imap( ~ test(tibble(!!.y := .x)))
-вывод
str(out)
#List of 2
# $ v1: tibble [20 × 1] (S3: tbl_df/tbl/data.frame)
# ..$ v1: int [1:20] 1 2 3 4 5 6 7 8 9 10 ...
# $ v2: tibble [20 × 1] (S3: tbl_df/tbl/data.frame)
# ..$ v2: int [1:20] 100 101 102 103 104 105 106 107 108 109 ...
Ответ №2:
Вы можете использовать setNames
:
tibble::tibble(v1=1:20,v2=100:119) %>% purrr::imap(~test(.x) %>% setNames(.y))
#$v1
# A tibble: 20 x 1
# v1
# <int>
# 1 1
# 2 2
# 3 3
# 4 4
# 5 5
#...
#...
#$v2
# A tibble: 20 x 1
# v2
# <int>
# 1 100
# 2 101
# 3 102
# 4 103
# 5 104
# 6 105
#...
#...
Комментарии:
1. Спасибо. Однако, если
test()
требуется, чтобы его входные данные были tibble (вместо vector), это не поможет.2. если
test()
требуется, чтобы входные данные были tibble, то обаimap
ormap
не помогут, так как оба они преобразуют столбец в вектор. Я не думаюsetNames
, что здесь возникнет какая-то проблема.3. Хорошо .. тогда я не совсем понимаю ваш комментарий. Может быть, если бы вы могли показать, какой результат вы ожидаете, или привести пример, в котором мой ответ не удался, я могу обновить свой ответ.
4. Используйте (по общему признанию) очень надуманную функцию
test<-function(data){glue::glue("Average: {colMeans(data)} in variable variable called {colnames(data)[1]}")}
— код akrun будет работать без ошибок.5. @Inferrator Это потому, что в его ответе tibble создается явно. Если вы измените мой ответ
tibble::tibble(v1=1:20,v2=100:119) %>% purrr::imap(~test(tibble(.x) %>% setNames(.y)))
, он будет работать аналогично.