#r #dictionary #dplyr #purrr
#r #словарь #dplyr #мурлыканье
Вопрос:
Я хочу разделить все числовые столбцы на общий коэффициент, используя разные коэффициенты в каждом подмножестве строк.
Репрезентативный пример — с iris
набором данных, если бы я хотел разделить все числовые столбцы для каждого Species
на другой коэффициент, например
- Установить значение на 1
- Разноцветный на 10
- Virginica на 100
Пробовал разделить, затем объединить — предоставить список факторов; разделить iris
список наборов данных фреймов данных по группам, сопоставить по обоим входам, затем рекомбинировать — но я не могу правильно отобразить карту
map_dfr(list(1,10,100), ~
iris %>%
group_split(Species) %>%
mutate(across(where(is.numeric), ~x / .x)))
Error in UseMethod("mutate_") :
no applicable method for 'mutate_' applied to an object of class "c('vctrs_list_of', 'vctrs_vctr', 'list')"
Или использовать map2
для двух входных данных списка:
map2(x = iris %>% group_split(Species),
y = list(1,10,100),
function(x,y)
mutate(across(where(is.numeric), .x / .y)))
Error: unexpected ')' in " mutate(across(where(is.numeric), .x / .y)))"
Ответ №1:
Вот рабочая версия с map2
:
map2(.x = iris %>% group_split(Species),
.y = list(1,10,100),
function(x, div) {
mutate(x, across(where(is.numeric), ~ .x / div))
})
Основное изменение заключается в том, что mutate()
требуется, чтобы фрейм данных был его первым аргументом, следовательно mutate(x, ...)
. Я также переименовал y
в div
, чтобы избежать путаницы. У нас есть 2 анонимные функции… function(x, div)
означает, что у нас есть аргумент x
, который является фреймом данных, и div
который является каждым делителем. Мы передаем x
в mutate
, а затем вторая анонимная функция (использующая ~
обозначение) нуждается в использовании .x
по умолчанию (для числовых столбцов), но должна использовать div
, поскольку она находится внутри (x, div)
функции.
Мне не очень нравится приведенный выше код, потому что он полагается на то, что .y
список находится в том же порядке, что и group_split
группы. Если бы это был мой код, я бы, вероятно, сделал это с помощью справочной таблицы и вместо этого объединил, что безопаснее, потому что связь между видами и делителем теперь понятна и проверяема.
div = tribble(
~Species, ~factor,
"setosa", 1,
"versicolor", 10,
"virginica", 100
)
iris %>%
left_join(div) %>%
mutate(across(where(is.numeric), ~.x / factor)) %>%
select(-factor)
Комментарии:
1. Спасибо @gregor-thomas, это превосходно — согласитесь, что простой
left_join / mutate
— это более чистый код, меньше шансов на ошибку при сопоставлении неправильного коэффициента с неправильным подмножеством данных и метод, который я буду использовать. Я был слишком ориентирован на карту — свежий взгляд всегда полезен 🙂 И спасибо за объяснениеmap2
вызова, сортировкиx
из.x
анонимных функций, на случай, если я использую его или подобное в будущем.