[英]How do I extract estimates and p-value from cor.test results across multiple groups?
我有一组数据,在多个时间点有多个组(下面的示例剪切):
我一直在尝试在每个状态和每个性别之间的 X 和 Y 之间进行多个 cor.test。
我很难弄清楚组比较,所以我按状态过滤并将我的性别 cor.tests 分别拆分为 Status = Red 和 Status = Blue(使用过滤器)。
这是我当前的代码,它在每个性别上运行 cor.test:
red_status <- all %>% filter(status == "Red")
cor_red <- by(red_status, red_status$gender,
FUN = function(df) cor.test(df$X, df$Y, method = "spearman"))
output 结果显示了每个性别的 3 个不同的 cor.test:
red_status$gengrp: M
Spearman's rank correlation rho
data: df$X and df$Y
S = 123.45, p-value = 0.123
alternative hypothesis: true rho is not equal to 0
sample estimates:
rho
0.123456
----------------------------------
red_status$gengrp: F
... (same output style as gengrp: M ^)
----------------------------------
red_status$gengrp: O
... (same output style as gengrp: M ^)
我想要做的是提取所有性别 cor.test 的估计值和 p 值,并将它们放在 dataframe 中。
我想我可以使用 data.frame() function 来提取性别名称和相关元素,然后为 p 值添加另一列,但是这样做给了我一个错误:
# Where red_status[1] is gender names (M,F,O) and red_status[[3:4]] are the Spearman p-value and rho estimate *within each gender category*
data.frame(group = dimnames(red_status)[1], est = as.vector(red_status)[[3]],
pval = as.vector(red_status[[4]])
Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) :
cannot coerce class ‘"htest"’ to a data.frame
由于我按 Status == Red 过滤,因此我必须再次重新运行代码以获得 Status == Blue 的性别 cor.test 结果,然后在最后将估计值和 p 值全部绑定到 1 df。
我的目标是能够创建一个数据框,显示每个状态和性别的相关估计和 p 值:
Status Gender Estimate(rho) P-value
Red M 1.23 0.123
Red F 0.45 0.054
Red O ... ...
Blue M 0.004 0.123
Blue F ... ...
Blue O ... ...
任何帮助/提示将不胜感激。
答案基于@Ruam Pimentel 关于 rstatix package 的评论。
使用管道 + cor_test() function,我可以按状态和性别分组来运行相关性测试。 cor_test() function 旨在 output dataframe 包含相关的所有元素(即统计、p 值、估计),所有这些都取决于选择的相关方法。
这是有效的代码:
r <- dfall %>%
group_by(status, gender) %>%
cor_test(X, Y, method = "spearman")
结果(编辑了数字):
status gengrp var1 var2 cor statistic p method
<chr> <fct> <chr> <chr> <dbl> <dbl> <dbl> <chr>
1 Red M X Y 0.98 -0.123 0.123 Spearman
2 Red F X Y 0.12 0.456 0.456 Spearman
3 Red O X Y 0.34 0.944 0.789 Spearman
4 Blue M X Y 0.56 0.246 0.101 Spearman
5 Blue F X Y 0.78 0.4107 0.111 Spearman
6 Blue O X Y 0.9 0.123 0.122 Spearman
虽然rstatix
解决方案比 Base R 解决方案需要的代码少得多,但我发布了一个代码来证明可以在 Base R 中创建请求的 output。
Base R 解决方案的关键是了解如何从cor.test()
导航 output object 以提取请求的内容,将其转换为单行数据帧,以及rbind()
将对象列表转换为单个数据帧。
首先,我们生成一些数据。
set.seed(9108171) # for reproducibility
gender <- rep(c("F","M", "O"),40)
status <- c(rep("Red",60),rep("Blue",60))
x <- round(rnorm(120,mean = 6,sd = 2),1)
y <- round(rnorm(120,mean = 8,sd = 1),1)
df <- data.frame(gender,status, x, y)
接下来,我们根据原始帖子中的代码筛选出红色项目,然后运行 cor.test() function。
# filter red
library(dplyr)
red_status <- filter(df,status == "Red")
cor_red <- by(red_status, red_status$gender,
FUN = function(df) cor.test(df$x, df$y, method = "spearman"))
最后我们使用lapply()
来提取数据并将其组合成一个数据框。 请注意提取运算符[[
形式的使用,它从cor.test()
生成的列表列表中删除了一层嵌套。 另请注意我们如何使用名称向量、 gender
类别来驱动lapply()
。 这些值用于区分先前调用cor.test()
时的分组。
# extract the required data
theResults <- lapply(c("F","M","O"),function(x){
aTest <- cor_red[[x]]
data.frame(status = "Red",
test = names(aTest$statistic),
value = aTest$statistic,
p_value = aTest$p.value,
rho = aTest$estimate)
})
# rbind the results into a single data frame
do.call(rbind,theResults)
...以及红色状态的结果:
> do.call(rbind,theResults)
status test value p_value rho
S Red S 1072.672 0.4137465 0.19347947
S1 Red S 1396.400 0.8344303 -0.04992459
S2 Red S 1281.132 0.8777763 0.03674259
我们可以对 Blue 状态重复该过程并将结果结合起来以获得以下结果:
> rbind(blueResults,redResults)
status test value p_value rho
S Blue S 1541.034 0.50402812 -0.15867211
S1 Blue S 1087.954 0.44253280 0.18198950
S2 Blue S 1880.742 0.06950608 -0.41409194
S3 Red S 1072.672 0.41374648 0.19347947
S11 Red S 1396.400 0.83443026 -0.04992459
S21 Red S 1281.132 0.87777629 0.03674259
>
生成最终表的完整脚本是:
set.seed(9108171) # for reproducibility
gender <- rep(c("F","M", "O"),40)
status <- c(rep("Red",60),rep("Blue",60))
x <- round(rnorm(120,mean = 6,sd = 2),1)
y <- round(rnorm(120,mean = 8,sd = 1),1)
df <- data.frame(gender,status, x, y)
# filter red
library(dplyr)
red_status <- filter(df,status == "Red")
cor_red <- by(red_status, red_status$gender,
FUN = function(df) cor.test(df$x, df$y, method = "spearman"))
# extract the required data
theResults <- lapply(c("F","M","O"),function(x){
aTest <- cor_red[[x]]
data.frame(status = "Red",
test = names(aTest$statistic),
value = aTest$statistic,
p_value = aTest$p.value,
rho = aTest$estimate)
})
# rbind the results into a single data frame
redResults <- do.call(rbind,theResults)
redResults
blue_status <- filter(df,status == "Blue")
cor_blue<- by(blue_status, blue_status$gender,
FUN = function(df) cor.test(df$x, df$y, method = "spearman"))
# extract the required data
theResults <- lapply(c("F","M","O"),function(x){
aTest <- cor_blue[[x]]
data.frame(status = "Blue",
test = names(aTest$statistic),
value = aTest$statistic,
p_value = aTest$p.value,
rho = aTest$estimate)
})
# rbind the results into a single data frame
blueResults <- do.call(rbind,theResults)
rbind(blueResults,redResults)
我认识到我可以将重复的代码抽象成一个支持 function 以减少解决方案所需的总代码行数,但这留给读者作为一个微不足道的练习。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.