Как преобразовать вывод функции «by» во фрейм данных в R? - PullRequest
0 голосов
/ 21 сентября 2018

Вот что я хочу сделать: у меня есть датафрейм df, определенный как:

col1 <- c("a","a","a","a","a","a","b","b","b","b","b","b")
col2 <- c("z","z","x","x","z","x", "z","z","x","x","z","x")
col3 <- c(1,2,3,4,5,6,7,8,9,10,11,12)
df <- data.frame(col1,col2,col3)

и функция pred, которая вычисляет среднее значение, определенное как:

pred <- function(subset_df){return(mean(subset_df$col3))}

Я хочукадр данных через функцию by в следующем формате:

col1 col2 col3_mean
a     x    4.33
a     z    2.66
b     x    10.33
b     z    8.66

В настоящее время я использую функцию by () для разделения этих данных на слои и применяю функцию pred (), которая вычисляет среднее значение

by_keys <- c("col1","col2")
data_sub <- by(df, data_sub[,by_keys], pred)  
data_sub <- do.call(rbind, data_sub)

Я получаю сообщение об ошибке: «Ошибка в do.call (rbind, data_sub): второй аргумент должен быть списком»

Я попытался найти решение из аналогичного шага, но яне получайте col1 и col2 в нужном формате

as.data.frame(vapply(data_sub,unlist,unlist(data_sub[[1]])))

Буду признателен за любую помощь в этом.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Действительно, by при настройке не вернет список, а упростит структуру, поскольку ваши выходные данные возвращают числовые векторы.Настройте функцию pred , чтобы она возвращала фреймы данных, которые, будучи неупрощенными структурами, заставят by вернуть список и затем могут быть переданы в do.call.

pred <- function(subset_df){    
  df <- data.frame(col1 = subset_df$col1[[1]], 
                   col2 = subset_df$col2[[1]],
                   col3_mean = mean(subset_df$col3)
                  )                      
  return(df)
}

data_sub_list <- by(df, df[,by_keys], pred)  
data_sub <- do.call(rbind, data_sub_list)
data_sub

#   col1 col2 col3_mean
# 1    a    x  4.333333
# 2    b    x 10.333333
# 3    a    z  2.666667
# 4    b    z  8.666667

* 1009.* Однако, как прокомментировал @Onyambu, этот тип группированной агрегации можно выполнить с aggregate, который будет возвращать фреймы данных.
# FORMULA VERSION
aggregate(col3 ~ col1 + col2, df, mean)
#   col1 col2 col3_mean
# 1    a    x  4.333333
# 2    b    x 10.333333
# 3    a    z  2.666667
# 4    b    z  8.666667

# NON-FORMULA VERSION
aggregate(df$col3, by=list(col1=df$col1, col2=df$col2), mean)
#   col1 col2         x
# 1    a    x  4.333333
# 2    b    x 10.333333
# 3    a    z  2.666667
# 4    b    z  8.666667

Обычно by (являясь объектно-ориентированной оболочкой для tapply) лучше всего подходит для выполнения больших, расширенных операций с фреймами данных, которые вам нужны для итеративного запуска подмножеств.На самом деле, если вам нужно несколько агрегатов, тогда становится полезным by:

pred <- function(subset_df){      
  df <- data.frame(col1 = subset_df$col1[[1]], 
                   col2 = subset_df$col2[[1]],
                   col3_mean = mean(subset_df$col3),
                   col3_sd = sd(subset_df$col3),
                   col3_median = median(subset_df$col3),
                   col3_min = min(subset_df$col3),
                   col3_max = max(subset_df$col3),
                   col3_sum = sum(subset_df$col3),
                   col3_25pct = quantile(subset_df$col3)[[2]],
                   col3_75pct = quantile(subset_df$col3)[[4]],
                   col3_IQR = IQR(subset_df$col3)
                  )      
  return(df)
}

data_sub_list <- by(df, df[,by_keys], pred)  
data_sub <- do.call(rbind, data_sub_list)

#   col1 col2 col3_mean  col3_sd col3_median col3_min col3_max col3_sum col3_25pct col3_75pct col3_IQR
# 1    a    x  4.333333 1.527525           4        3        6       13        3.5        5.0      1.5
# 2    b    x 10.333333 1.527525          10        9       12       31        9.5       11.0      1.5
# 3    a    z  2.666667 2.081666           2        1        5        8        1.5        3.5      2.0
# 4    b    z  8.666667 2.081666           8        7       11       26        7.5        9.5      2.0
0 голосов
/ 21 сентября 2018

Использование dplyr:

library(dplyr)

df %>% group_by(col1, col2) %>% 
  summarize(col3_mean = mean(col3)) %>%
  as.data.frame


  col1 col2 col3_mean
1    a    x     4.333
2    a    z     2.667
3    b    x    10.333
4    b    z     8.667
...