根据 p 值有条件地将 geom_smooth 添加到 ggplot 构面

Posted

技术标签:

【中文标题】根据 p 值有条件地将 geom_smooth 添加到 ggplot 构面【英文标题】:Add geom_smooth to ggplot facets conditionally based on p-value 【发布时间】:2021-11-12 12:40:02 【问题描述】:

我正在使用 ggplot 可视化许多线性回归并按组对它们进行分面。如果 P

我设法使用循环从 lm() 中为每个回归提取 P 值,然后将它们与用于绘图的数据连接起来。然后我添加另一列颜色名称以传递给 aes(),根据 P 值有条件地确定,并使用 scale_color_identity() 来实现我的目标。

这是一个例子:

library(tidyverse)

#make mtcars a tibble and cyl a factor, for convenience
mtcars1 <- as_tibble(mtcars) %>% dplyr::mutate(cyl = as.factor(cyl))

#initialize a list to store p-values from lm() for each level of factor
p.list <- vector(mode = "list", length = length(levels(mtcars1$cyl)))
names(p.list) <- levels(mtcars1$cyl)

#loop to calculate p-values for each level of mtcars$cyl
for(i in seq_along(levels(mtcars1$cyl)))
  mtcars.sub <- mtcars1 %>% dplyr::filter(cyl == levels(.$cyl)[i])
  
  lm.pval <- mtcars.sub %>% 
    dplyr::distinct(cyl) %>% 
    dplyr::mutate(P = 
                    summary(lm(mpg ~ disp, data = mtcars.sub))$coefficients[2,4] ##extract P-value
    )
  
  p.list[[i]] <- lm.pval


#join p-values to dataset and add column to use with scale_color_identity()
mtcars.p <- mtcars1 %>% dplyr::left_join(dplyr::bind_rows(p.list, .id = "cyl"), by = "cyl") %>% 
  dplyr::mutate(p.color = ifelse(P < 0.05, "black",
                                 ifelse(P < 0.10, "lightblue", NA)))

#plot
ggplot(data = mtcars.p, aes(x = disp, y = mpg)) +
  geom_smooth(method = "lm",
              se = FALSE,
              aes(color = p.color)) +
  geom_point() +
  scale_color_identity(name = NULL,
                       na.translate = FALSE,
                       labels = c("P < 0.05", "P < 0.10"),
                       guide = "legend") +
  facet_wrap(~cyl, scales = "free")

对于应该相对容易的事情来说,这似乎是太多的初始步骤。这些步骤是必要的,还是有更有效的方法来做到这一点? ggplot 或任何其他软件包可以自己执行此操作,而无需先从 lm() 中提取 p 值吗?

【问题讨论】:

您可以使用broom::tidy 来获取 lm 的输出,即list(tidy(lm(... 【参考方案1】:

我们可以通过操作分组来简化步骤,并且不是提取每个组件,而是输出可以在tidy from broom 的小标题中

library(broom)
library(dplyr)
library(tidyr)
mtcars1 %>% 
   group_by(cyl) %>% 
   summarise(out = list(tidy(lm(mpg ~ disp, data = cur_data())))) %>% 
   unnest(out)

-输出

# A tibble: 6 x 6
  cyl   term        estimate std.error statistic    p.value
  <fct> <chr>          <dbl>     <dbl>     <dbl>      <dbl>
1 4     (Intercept) 40.9       3.59       11.4   0.00000120
2 4     disp        -0.135     0.0332     -4.07  0.00278   
3 6     (Intercept) 19.1       2.91        6.55  0.00124   
4 6     disp         0.00361   0.0156      0.232 0.826     
5 8     (Intercept) 22.0       3.35        6.59  0.0000259 
6 8     disp        -0.0196    0.00932    -2.11  0.0568    

【讨论】:

【参考方案2】:

指定回归函数后,可以在 ggplot 中包含线函数:

myline<-lm(mpg ~ disp, data = mtcars)
ggplot(data = mtcars, aes(x = disp, y = mpg)) +
  geom_abline(slope = coef(myline)[[2]], intercept = coef(myline)[[1]],     color='blue')+
  geom_point(color='red') +
  scale_color_identity(name = NULL,
                   na.translate = FALSE,
                   labels = c("P < 0.05", "P < 0.10"),
                   guide = "legend") +
  facet_wrap(~cyl, scales = "free")

同上,你也可以使用这个geom_smooth()命令:

geom_smooth(slope = coef(myline)[[2]], intercept = coef(myline)[[1]], color='blue',se=F,method='lm')+

【讨论】:

以上是关于根据 p 值有条件地将 geom_smooth 添加到 ggplot 构面的主要内容,如果未能解决你的问题,请参考以下文章

根据 selectOneMenu 值有条件地渲染组件

根据 selectOneMenu 值有条件地渲染组件

根据外部值有条件地应用管道步骤

如何根据另一个参数的值有条件地禁用 Storybook 中的控件?

如何根据传入参数的值有条件地应用 GraphQL 过滤器?

根据当前节点值有条件地匹配