基于 groups/categories 执行多个配对 t 检验
Perform multiple paired t-tests based on groups/categories
我一直在为 Rstudio 中的多个类别执行 t.tests。我想得到每个产品类型的 t.test 的结果,比较在线和离线价格。我有超过 800 种产品类型,所以我不想为每个产品组手动执行此操作。
我有一个名为 data 的数据框(超过 200 万行),如下所示:
> 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+ 个数据帧,然后执行 800 次 t 检验。
我用列表和 lapply 尝试过,但到目前为止它不起作用。我还在多列上尝试了 t-Test:
https://sebastiansauer.github.io/multiple-t-tests-with-dplyr/
然而最后他还是手动插入男&女(对我来说超过800个类别)。
一种方法是使用 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)[c(1:9)])
要在数据框中获取结果,您必须 rbind
它:
type.convert(as.data.frame(do.call(rbind, result)), as.is=TRUE)
# statistic parameter p.value conf.int estimate null.value stderr alternative method
# A 2.267787 2 0.1514719 -20.25867, 32.25867 6 0 2.645751 two.sided Paired t-test
# B -0.06666667 1 0.9576214 -477.9256, 476.9256 -0.5 0 7.5 two.sided Paired t-test
# C 1.073154 3 0.3618456 -9.996192, 14.496192 2.25 0 2.096624 two.sided Paired t-test
或者,使用管道:
do.call(rbind, result) |> as.data.frame() |> type.convert(as.is=TRUE)
数据
data <- structure(list(Product_type = c("A", "B", "B", "A", "C", "C",
"C", "A", "C"), Price_Online = c(48L, 29L, 32L, 38L, 32L, 31L,
28L, 47L, 40L), Price_Offline = c(37L, 22L, 40L, 36L, 27L, 35L,
24L, 42L, 36L)), class = "data.frame", row.names = c("1", "2",
"3", "4", "5", "6", "7", "8", "9"))
简洁的方法是使用 dplyr 和 broom:
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))))
比我的基本 r 解决方案更具可读性,它会为您处理列名!
编辑
比使用 do
(参见 r4ds)更惯用的方法是使用 nest
为每种产品类型创建嵌套数据框,然后 运行 t 检验对于每个嵌套数据帧,使用 purrr
中的 map
。
library(broom)
library(dplyr)
library(purrr)
library(tidyr)
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)
我一直在为 Rstudio 中的多个类别执行 t.tests。我想得到每个产品类型的 t.test 的结果,比较在线和离线价格。我有超过 800 种产品类型,所以我不想为每个产品组手动执行此操作。
我有一个名为 data 的数据框(超过 200 万行),如下所示:
> 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+ 个数据帧,然后执行 800 次 t 检验。
我用列表和 lapply 尝试过,但到目前为止它不起作用。我还在多列上尝试了 t-Test: https://sebastiansauer.github.io/multiple-t-tests-with-dplyr/
然而最后他还是手动插入男&女(对我来说超过800个类别)。
一种方法是使用 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)[c(1:9)])
要在数据框中获取结果,您必须 rbind
它:
type.convert(as.data.frame(do.call(rbind, result)), as.is=TRUE)
# statistic parameter p.value conf.int estimate null.value stderr alternative method
# A 2.267787 2 0.1514719 -20.25867, 32.25867 6 0 2.645751 two.sided Paired t-test
# B -0.06666667 1 0.9576214 -477.9256, 476.9256 -0.5 0 7.5 two.sided Paired t-test
# C 1.073154 3 0.3618456 -9.996192, 14.496192 2.25 0 2.096624 two.sided Paired t-test
或者,使用管道:
do.call(rbind, result) |> as.data.frame() |> type.convert(as.is=TRUE)
数据
data <- structure(list(Product_type = c("A", "B", "B", "A", "C", "C",
"C", "A", "C"), Price_Online = c(48L, 29L, 32L, 38L, 32L, 31L,
28L, 47L, 40L), Price_Offline = c(37L, 22L, 40L, 36L, 27L, 35L,
24L, 42L, 36L)), class = "data.frame", row.names = c("1", "2",
"3", "4", "5", "6", "7", "8", "9"))
简洁的方法是使用 dplyr 和 broom:
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))))
比我的基本 r 解决方案更具可读性,它会为您处理列名!
编辑
比使用 do
(参见 r4ds)更惯用的方法是使用 nest
为每种产品类型创建嵌套数据框,然后 运行 t 检验对于每个嵌套数据帧,使用 purrr
中的 map
。
library(broom)
library(dplyr)
library(purrr)
library(tidyr)
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)