#r #loops #dplyr #apply
#r #циклы #dplyr #применить
Вопрос:
Я пытаюсь применить функции к нескольким переменным во фрейме данных. Ниже приведен пример того, что я пытаюсь сделать.
#Creating data frame
df <- data.frame (Year = c(1,2,3),
"Revenue_change" = c(0.43, 0.56, 0.48),
"Costs_change" = c(0.31, 0.41, 0.39))
#Create vector to use for loop
var <- c("Revenue_change", "Costs_change")
#Using loop to put revenue and cost in percentage terms (multiplying by a 100)
for (v in var) {
df <- df %>%
mutate(v = v * 100)
}
Я буду применять это к нескольким переменным в гораздо большем фрейме данных, и поскольку я не могу заставить этот цикл работать в моем основном наборе данных, в настоящее время у меня очень повторяющийся код, как показано ниже:
KPI <- KPI %>%
#Total sales
mutate(Rank_sales = rank(desc(`Total Sales_% Var`))) %>%
mutate(Points_sales = (n() - (Rank_sales - 1)) * 10) %>%
#Donated sales
mutate(Rank_donated = rank(desc(`Donated Sales_% Var`))) %>%
mutate(Points_donated = (n() - (Rank_donated - 1)) * 10) %>%
#New good sales
mutate(Rank_new = rank(desc(`New Goods Sales_% Var`))) %>%
mutate(Points_new = (n() - (Rank_new - 1)) * 10) %>%
#Gift aid
mutate(Rank_gift = rank(desc(`Gift Aid_%`))) %>%
mutate(Points_gift = (n() - (Rank_gift - 1)) * 10) %>%
#Net profit
mutate(Rank_net = rank(desc(`Net Profit_£ Var`))) %>%
mutate(Points_net = (n() - (Rank_net - 1)) * 10) %>%
#Volunteer
mutate(Rank_volunteer = rank(desc(`Volunteer Hrs_for every £1k Sales`))) %>%
mutate(Points_volunteer = (n() - (Rank_volunteer - 1)) * 10)
Надеемся, что цикл или функция apply помогут уменьшить повторяемость текущего кода.
Комментарии:
1. Мне неясно, как первая часть вашего кода относится ко 2-й части. Но чтобы дать указатель, я бы изменил данные с широких на длинные
tidyr::pivot_longer()
, затем использовалgroup_by()
для применения вычисления для каждого набора переменных, а затем вам нужно только один раз применить вызов mutate. (Также обратите внимание, что вам не нужно использовать mutate для одного преобразования, вы можете применить их все в одном вызове mutate).2. Первый пример — просто предоставить что-то, что имеет воспроизводимые данные, тогда как второй фрагмент показывает образец моего фактического кода. Я знаю об использовании
group_by
, но предпочел бы решение, которое применяет функции к нескольким переменным без необходимости изменения формы, поскольку эти данные я географически сопоставляю с помощью пакета листовок, и это лучше работает с использованием широких данных.3. Сгенерированные данные полезны только тогда, когда они делают последующий код воспроизводимым.
Ответ №1:
Сложно проверить, действительно ли это работает без выборки ваших фактических данных, но что-то вроде этого должно работать:
myvars <- c("Total Sales_% Var", "Donated Sales_% Var", "New Goods Sales_% Var", "Gift Aid_%", "Net Profit_£ Var", "Volunteer Hrs_for every £1k Sales")
Points_fun <- function(x) {
rank_var <- rank(desc(x))
(n() - (rank_var - 1)) * 10)
}
mutate(KPI, across(all_of(myvars), ~ rank(desc(.x)), .names = "Rank_{.col}"),
across(all_of(myvars), Points_fun, .names = "Points_{.col}"))