R — создать сводную таблицу с двойной записью

#r #dataframe #dplyr #pivot

#r #фрейм данных #dplyr #сводная

Вопрос:

Я новичок в R, поэтому прошу прощения, если это простой вопрос. Я часто использую Excel для создания таблиц с «двойными записями». Вероятно, название «двойная таблица» не самое точное, но я бы не знал, как описать это иначе. Я в основном начинаю с больших таблиц, а затем создаю новую, где я усредняю группировку данных по двум столбцам, а затем отображаю ее в виде матрицы. Я поделюсь с вами совершенно функциональным примером R, который я сам закодировал. Мой вопрос: есть ли более простой / лучший способ сделать это? Это мой рабочий код:

 require(dplyr)
df <- mtcars
output_var <- 'disp'
rows_var <- 'cyl'
col_var <- 'am'
output_name <- paste0("Avg. ",output_var)
one_way_table <- df %>%
  group_by(eval(parse(text=rows_var)),     eval(parse(text=col_var))  ) %>%
  summarise(output=mean(    eval(parse(text=output_var))     ))  

one_way_table <- data.frame(one_way_table, check.rows = F, check.names = F, stringsAsFactors = F)
colnames(one_way_table) <- c(rows_var, col_var, output_name)

unique_row_items <- unique(one_way_table[,rows_var])
unique_col_items <- unique(one_way_table[,col_var])
x_rows <- rep(unique_row_items, length(unique_col_items))
y_cols <- rep(unique_col_items, length(unique_row_items))

new_df <- data.frame(x = x_rows, y = y_cols, check.rows = F, check.names = F, stringsAsFactors = F)
colnames(new_df) <- c(rows_var, col_var)

new_df <- base::merge(new_df, one_way_table, by = c(rows_var, col_var), all.x=T)
m <- matrix(new_df[, output_name],    ncol= length(unique(new_df[,col_var])) )
df_matrix <- data.frame(m, check.rows = F, check.names = F, stringsAsFactors = F)
  

Возможно, есть более эффективный способ сделать это.
Обратите внимание, что, поскольку это будет закодировано внутри функции, мне пришлось использовать имена переменных, которые определяют, какие столбцы я хочу использовать для анализа.
Спасибо

Ответ №1:

Возможное решение вашей проблемы может быть получено из tidyverse . Вот пример изменения формы ваших данных и агрегирования с помощью mean:

 library(tidyverse)
#Data
df <- mtcars
#Code
df %>% pivot_longer(cols = -c(cyl,am)) %>% filter(name=='disp') %>%
  group_by(cyl,am) %>% summarise(Mean=mean(value)) %>%
  pivot_wider(names_from = am,values_from=Mean)
  

Вывод:

 # A tibble: 3 x 3
# Groups:   cyl [3]
    cyl   `0`   `1`
  <dbl> <dbl> <dbl>
1     4  136.  93.6
2     6  205. 155  
3     8  358. 326 
  

Которая близка к df_matrix окончательному выводу вашего кода.

Ответ №2:

Если нам нужно выполнить поворот, это можно сделать более простым способом. Мы select выбираем интересующие столбцы и используем их pivot_wider с values_fn указанием, как mean будет применяться к столбцам, выбранным на values_from

 library(dplyr)
library(tidyr)
mtcars %>%
    select(cyl, am, disp) %>% 
    pivot_wider(names_from = am, values_from = disp, values_fn = mean)
# A tibble: 3 x 3
#    cyl   `1`   `0`
#  <dbl> <dbl> <dbl>
#1     6 155    205.
#2     4  93.6  136.
#3     8 326    358.