Использование циклов For в R для применения одной и той же функции к нескольким переменным во фрейме данных

#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}"))