Выполните несколько парных t-тестов на основе групп / категорий

Я застрял в проведении t.tests для нескольких категорий в Rstudio. Я хочу получить результаты t.test для каждого типа продукта, сравнивая онлайн и оффлайн цены. У меня более 800 видов продукции, поэтому я не хочу делать это вручную для каждой группы продуктов.

У меня есть датафрейм (более 2 миллионов строк) с именем data, который выглядит следующим образом:

> Product_type   Price_Online   Price_Offline   
1   A            48             37
2   B            29             22
3   B            32             40
4   A            38             36
5   C            32             27
6   C            31             35
7   C            28             24
8   A            47             42
9   C            40             36

В идеале я хочу, чтобы R записал результат t.test в другой фрейм данных с именем product_types:

    > Product_type   
    1   A           
    2   B            
    3   C          
    4   D          
    5   E         
    6   F            
    7   G            
    8   H            
    9   I            
   800 ...

будет выглядеть так:

> Product_type   t         df       p-value   interval    mean of difference            
    1   A           
    2   B            
    3   C          
    4   D          
    5   E         
    6   F            
    7   G            
    8   H            
    9   I            
   800 ...

Это формула, если бы у меня были все типы продуктов в разных фреймах данных:

t.test(Product_A$Price_Online, Product_A$Price_Offline, mu=0, alt="two.sided", paired = TRUE, conf.level = 0.99)

Должен быть более простой способ сделать это. В противном случае мне нужно создать более 800 фреймов данных, а затем выполнить t-тест 800 раз.

Я пытался что-то со списками и лапы, но пока это не работает. Я также попробовал t-тест на нескольких столбцах: https://sebastiansauer.github.io/multiple-t-tests-with-dplyr/

Тем не менее, в конце он все еще вручную вводит мужской и женский (для меня более 800 категорий).

2 ответа

Решение

Один из способов сделать это - использовать by:

result <- by(data, data$Product_type, 
    function(x) t.test(x$Price_Online, x$Price_offline, mu=0, alt="two.sided", paired = TRUE, conf.level = 0.99))

Единственным недостатком является то, что by возвращает список, и если вы хотите, чтобы ваши результаты в кадре данных, вы должны преобразовать его:

df <- data.frame(t(matrix(unlist(result), nrow = 10)))

Затем вам нужно будет добавить тип продукта и имена столбцов вручную:

df$Product_type <- names(result)
names(df) <- names(result$A)

Аккуратный способ сделать это - использовать dplyr и метлу:

library(dplyr)
library(broom)

df <- data %>% 
  group_by(Product_type) %>% 
  do(tidy(t.test(.$Price_Online, 
                 .$Price_Offline, 
                 mu = 0, 
                 alt = "two.sided", 
                 paired = TRUE, 
                 conf.level = 0.99))))

Гораздо более удобочитаемо, чем мое базовое решение, и оно обрабатывает имена столбцов для вас!

РЕДАКТИРОВАТЬ Более идиоматический способ сделать это, чем использовать do (см. r4ds) использовать nest чтобы создать вложенные фреймы данных для каждого типа продукта, а затем запустить t-тест для каждого вложенного фрейма данных, используя map от purrr,

library(broom)
library(dplyr)
library(purrr)

t_test <- function(df, mu = 0, alt = "two.sided", paired = T, conf.level = .99) {
  tidy(t.test(df$Price_Offline, 
              df$Price_Online,
              mu = mu, 
              alt = alt,
              paired = paired,
              conf.level = conf.level))
}

d <- df %>%
  group_by(Product_type) %>%
  nest() %>%
  mutate(ttest = map(data, t_test)) %>%
  unnest(ttest, .drop = T)
Другие вопросы по тегам