一个 R 函数,用于执行 t 检验以整齐地比较均值和输出结果
An R function to perform t-test to compare means and output result in a tidy way
我有具有以下结构的数据框(一个字符和 3 个数字),但数字列的名称各不相同:
structure(list(treatment = c("product", "product", "product", "product", "product", "control", "control", "control", "control", "control"), t0 = 1:10, t1 = c(1, 3, 5, 7, 9, 11, 13, 15, 17, 19), t2 = c(1, 4, 7, 10, 13, 16, 19, 22, 25, 28)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L))
treatment t0 t1 t2
<chr> <int> <dbl> <dbl>
1 product 1 1 1
2 product 2 3 4
3 product 3 5 7
4 product 4 7 10
5 product 5 9 13
6 control 6 11 16
7 control 7 13 19
8 control 8 15 22
9 control 9 17 25
10 control 10 19 28
我想设置一个函数来执行 t 检验和比较均值(t1 vs t0 和 t2 vs t0)。然而,这个函数需要能够在我拥有的所有数据框中工作,也就是说,包括那些数字列不被称为 t0、t1、t2 的数据框。所以我认为它可能通过调用函数内的列号来工作,但 t.test 函数似乎不接受。此外,以整洁的方式获得函数的结果会很好。最后,它会像这样工作:
my_ttest_func(df)
t1_t0 t estimate p_value
<chr> <dbl> <dbl> <dbl>
1 product 5.94 7.19 0.0000104
2 control 1.98 2.32 0.0327
t2_t0 t estimate p_value
<chr> <dbl> <dbl> <dbl>
1 product 4.20 5.86 0.000339
2 control 1.95 2.55 0.0343
通过将 df 旋转为长格式,我得到了接近我预期的结果,但只能通过调用我想要比较的级别来工作。也只给出了一个比较,所以我应该调用函数两次。由于我的数据帧的结构始终相同,我可以将以下代码放入 my_ttest_func()
但需要以通用方式引用时间级别。
df %>% pivot_longer(!treatment, names_to = "time", values_to = "values") %>%
group_by(treatment) %>%
summarise(across(.cols = values, ~ list(broom::tidy(t.test(.[time == "t2"],
.[time == "t0"],
alternative = "greater",
paired=TRUE)) %>%
select(statistic, estimate, p.value)))) %>%
unnest(values)
treatment statistic estimate p.value
<chr> <dbl> <dbl> <dbl>
1 control 9.90 14 0.000292
2 product 2.83 4 0.0237
提前致谢
您可以使用嵌套的 map
函数:
library(purrr)
library(dplyr)
df %>%
split(~treatment) %>%
map_dfr(
~.x %>%
summarise(
across(
3:4,
~t.test(.x,
!!sym(colnames(df)[2]),
alternative = "greater",
paired=TRUE) %>%
broom::tidy() %>%
select(statistic, estimate, p.value)
)
) %>%
map_dfr(bind_rows, .id = "name"),
.id = "treatment") %>%
arrange(name, treatment)
这个returns
# A tibble: 4 x 5
treatment name statistic estimate p.value
<chr> <chr> <dbl> <dbl> <dbl>
1 control t1 9.90 7 0.000292
2 product t1 2.83 2 0.0237
3 control t2 9.90 14 0.000292
4 product t2 2.83 4 0.0237
这不完全是您想要的输出,但您可以继续努力。
由于您的 t0
列始终排在第二位,我们可以在 summarise(across(...))
结构中使用列名作为 t.test
的输入。
新列 name
包含用于测试的变量 t0
。
我有具有以下结构的数据框(一个字符和 3 个数字),但数字列的名称各不相同:
structure(list(treatment = c("product", "product", "product", "product", "product", "control", "control", "control", "control", "control"), t0 = 1:10, t1 = c(1, 3, 5, 7, 9, 11, 13, 15, 17, 19), t2 = c(1, 4, 7, 10, 13, 16, 19, 22, 25, 28)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L))
treatment t0 t1 t2
<chr> <int> <dbl> <dbl>
1 product 1 1 1
2 product 2 3 4
3 product 3 5 7
4 product 4 7 10
5 product 5 9 13
6 control 6 11 16
7 control 7 13 19
8 control 8 15 22
9 control 9 17 25
10 control 10 19 28
我想设置一个函数来执行 t 检验和比较均值(t1 vs t0 和 t2 vs t0)。然而,这个函数需要能够在我拥有的所有数据框中工作,也就是说,包括那些数字列不被称为 t0、t1、t2 的数据框。所以我认为它可能通过调用函数内的列号来工作,但 t.test 函数似乎不接受。此外,以整洁的方式获得函数的结果会很好。最后,它会像这样工作:
my_ttest_func(df)
t1_t0 t estimate p_value
<chr> <dbl> <dbl> <dbl>
1 product 5.94 7.19 0.0000104
2 control 1.98 2.32 0.0327
t2_t0 t estimate p_value
<chr> <dbl> <dbl> <dbl>
1 product 4.20 5.86 0.000339
2 control 1.95 2.55 0.0343
通过将 df 旋转为长格式,我得到了接近我预期的结果,但只能通过调用我想要比较的级别来工作。也只给出了一个比较,所以我应该调用函数两次。由于我的数据帧的结构始终相同,我可以将以下代码放入 my_ttest_func()
但需要以通用方式引用时间级别。
df %>% pivot_longer(!treatment, names_to = "time", values_to = "values") %>%
group_by(treatment) %>%
summarise(across(.cols = values, ~ list(broom::tidy(t.test(.[time == "t2"],
.[time == "t0"],
alternative = "greater",
paired=TRUE)) %>%
select(statistic, estimate, p.value)))) %>%
unnest(values)
treatment statistic estimate p.value
<chr> <dbl> <dbl> <dbl>
1 control 9.90 14 0.000292
2 product 2.83 4 0.0237
提前致谢
您可以使用嵌套的 map
函数:
library(purrr)
library(dplyr)
df %>%
split(~treatment) %>%
map_dfr(
~.x %>%
summarise(
across(
3:4,
~t.test(.x,
!!sym(colnames(df)[2]),
alternative = "greater",
paired=TRUE) %>%
broom::tidy() %>%
select(statistic, estimate, p.value)
)
) %>%
map_dfr(bind_rows, .id = "name"),
.id = "treatment") %>%
arrange(name, treatment)
这个returns
# A tibble: 4 x 5
treatment name statistic estimate p.value
<chr> <chr> <dbl> <dbl> <dbl>
1 control t1 9.90 7 0.000292
2 product t1 2.83 2 0.0237
3 control t2 9.90 14 0.000292
4 product t2 2.83 4 0.0237
这不完全是您想要的输出,但您可以继续努力。
由于您的 t0
列始终排在第二位,我们可以在 summarise(across(...))
结构中使用列名作为 t.test
的输入。
新列 name
包含用于测试的变量 t0
。