使用 group_by 创建相关性和 p 值的数据框,然后在 R 中绘制误差条

Create dataframe of correlation and p values using group_by then plot with error bars in R

我想绘制数据集中几个因素之间的相关性。如果可能,我想尝试为这些绘制的值添加误差条或晶须。 在计算值之前,我首先想根据其中一列中的值对它们进行分组。如果可能的话,我想使用 tidyverse 解决方案。我可以使用 cor() 实现其中一半,但我不知道如何添加包含 p 值的附加列。

我认为 iris 数据集很好地展示了我想做的事情。实际数据使用沿 x 轴的时间序列。我指定 spearman 是因为这是我分析中使用的相关性,而不是因为它是 iris 数据集中的正确选择。我看到其他一些 posts 建议使用 cor.test 并从中提取值,但我不确定如何将其应用回条形图以用作误差线。下面是创建基本条形图的代码。

Edit 我已经将示例从使用 mtcars 数据集更改为 iris 数据集因为我认为它更好地反映了我的数据。虽然 jay.sf 对问题的最初回答适用于 mtcars 集并且非常感谢,但它不适用于我的数据集并且 iris 集抛出了与我相同的错误有。此外,我没有在原文中说明这一点,但 tidyverse 解决方案更可取,但不是必需的。

我认为我正在寻找的答案可能包含在这里,但我仍在努力找出细节:https://dominicroye.github.io/en/2019/tidy-correlation-tests-in-r/

iristest <- iris %>%
  group_by(Species) %>%
  summarise(COR = cor(Sepal.Length,Sepal.Width, method = "spearman", use="complete.obs"))

ggplot(data = iristest) +
  aes(x = Species, y = COR) +
  geom_bar(stat = "identity") +
  theme_minimal()

原样,iristest 提供此输出:

    Species     COR
1   setosa      0.7553375
2   versicolor  0.5176060
3   virginica   0.4265165

我认为理想情况下,我希望输出在 COR 列之后添加 p 值。

    Species     COR          p-value
1   setosa      0.7553375    ###
2   versicolor  0.5176060    ###
3   virginica   0.4265165    ###

cor.test 生成一个列表,其中实际上存储了您需要的所有内容。因此,只需编写一个获取所需值的函数即可。我们可以在这里使用 by ,它会产生一个列表,我们可以 rbind 得到一个具有完美行名称的矩阵以进行绘图。列表数据帧的 rbind 需要 do.call

res <- do.call(rbind, by(iris, iris$Species, function(x) { 
  rr <- with(x, cor.test(Sepal.Length, Sepal.Width, method="pearson")) 
  return(c(rr$estimate, CI=rr$conf.int)) 
})) 
#                  cor       CI1       CI2
# setosa     0.7425467 0.5851391 0.8460314
# versicolor 0.5259107 0.2900175 0.7015599
# virginica  0.4572278 0.2049657 0.6525292

请注意,method="spearman" 不适用于 iris 等相关数据,因此我在这里使用了 "pearson"

为了绘制数据,我推荐 R 附带的 barplot。我们存储条形位置 b <- 并将它们用作 arrows 的 x 坐标。对于 y 坐标,我们从矩阵中获取值。

b <- barplot(res[,1], ylim=c(0, range(res)[2]*1.1), 
             main="My Plot", xlab="cyl", ylab="Cor. Sepal.Length ~ Sepal.Width")
arrows(b, res[,2], b, res[,3], code=3, angle=90, length=.1)
abline(h=0)
box()

主要使用 tidyverse...

这是与 Spearman 完成的关联:

library(tidyverse)
library(RVAideMemoire)

iristest <-  iris %>%
+ group_by(Species) %>%
+ group_modify(~ glance(spearman.ci(.x$Sepal.Width, .x$Sepal.Length))


iristest
# A tibble: 3 x 5
# Groups:   Species [3]
  Species    estimate conf.low.Inf conf.high.Sup method                     
  <fct>         <dbl>        <dbl>         <dbl> <chr>                      
1 setosa        0.755        0.599         0.857 Spearman's rank correlation
2 versicolor    0.518        0.251         0.724 Spearman's rank correlation
3 virginica     0.427        0.131         0.653 Spearman's rank correlation

使用 ggplot...

ggplot(iristest, aes(x = Species, y = estimate)) 
+ geom_bar(stat="identity") 
+ geom_errorbar(aes(ymin=conf.low.Inf, ymax=conf.high.Sup), width=.2, position=position_dodge(.9))

这是一个实现所要求的版本。 分解成步骤,它比上面的例子稍微长一些。此版本仅使用基础 R,但某些人可能会感兴趣。

# Just extract the columns used in your question
data = iris[, c("Sepal.Length", "Sepal.Width", "Species")]

# Group the data by species
grouped.data = by(data, (data$Species), list)
# Run the function 'cor.test' (from stats) over the data from each species
cor.results = lapply(grouped.data, function(x) cor.test(x$Sepal.Length, x$Sepal.Width, method = "spearman", exact = FALSE) )
# Extract the rho and p-value
rho = sapply(cor.results, "[[", "estimate"))
p = sapply(cor.results, "[[", "p.value")
# Bundle the results into a data.frame (or whatever data structure you prefer)
data.frame(Species = names(cor.results), COR = rho, `p-value` = p, row.names = NULL)
     Species       COR      p.value
1     setosa 0.7553375 2.316710e-10
2 versicolor 0.5176060 1.183863e-04
3  virginica 0.4265165 2.010675e-03

[请参阅 ?cor.test 中有关使用这些数据所必需的 exact = FALSE 的注释。]