Выполните несколько парных 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)