Создание нового среднего столбца в al oop с помощью пользовательской функции - PullRequest
3 голосов
/ 04 марта 2020

I sh для создания нового столбца при каждом вызове сгруппированной средней функции для всех типов факторных данных.

Я могу скопировать только решающий результат, но только на одну факторную переменную A .

   df <- data.frame(
      target = c(1, 4, 8, 9, 2, 1, 3, 5, 7, 1),
      A = c("A", "Z", "N", "A", "Z"),
      B = c("B", "Q", "G", "B", "T"),
      C = c("C", "Y", "C", "P", "Y")
    )

grouped_mean <- function(data, summary_var, ...) {
  summary_var <- enquo(summary_var)

  data %>%
    # Selects only factor data types and a target column
    select(which(map_chr(., class) == "factor"), !!summary_var) %>%
    group_by(...) %>%
    # Over here I am not able to change column name, so that it yields Mean_A, Mean_B and Mean_C
    mutate(mean = mean(!!summary_var)) %>%
    ungroup()
}

grouped_mean(data = df, 
             group_var = A, 
             summary_var = target)

Я попытался зациклить его:

map_df(df, grouped_mean(data = df, summary_var = target))

Но я получаю эту ошибку:

Ошибка: невозможно преобразовать объект tbl_df/tbl/data.frame к функции

Вопросы и вводные данные:

  1. Я не уверен, как сделать функцию, которая динамически меняет имя в функции преобразования, из имени означает * От 1022 * до mean_A , mean_B и mean_ c
  2. Я попытался использовать функцию map_df для l oop каждого элемента df , но безуспешно. Идея заключается в создании новых столбцов, которые являются средством целевой функции.

1 Ответ

2 голосов
/ 04 марта 2020

Вот немного странное решение, но оно должно работать для вас (если вы согласны с указанием target в качестве столбца, для которого вы хотите получить среднее значение). Это просто использует mutate_if() и использует поднабор с tapply(), чтобы получить ваши средства.

Затем он использует rename_at() для изменения имен в соответствии с желаемым результатом. Если вы хотите, чтобы он был в нижнем регистре, вы можете обернуть gsub() с tolower()

df %>%
  mutate_if(is.factor, list(Mean = ~tapply(df$target, ., mean)[.])) %>%
  rename_at(vars(ends_with("Mean")), ~gsub("(.*?)_(.*)", "\\2_\\1", .))

   target A B C Mean_A Mean_B Mean_C
1       1 A B C    4.5    4.5   3.75
2       4 Z Q Y    2.5    3.5   2.50
3       8 N G C    6.5    6.5   3.75
4       9 A B P    4.5    4.5   8.00
5       2 Z T Y    2.5    1.5   2.50
6       1 A B C    4.5    4.5   3.75
7       3 Z Q Y    2.5    3.5   2.50
8       5 N G C    6.5    6.5   3.75
9       7 A B P    4.5    4.5   8.00
10      1 Z T Y    2.5    1.5   2.50
...