从geom_smooth()中提取多条趋势线的斜率

7

我将使用ggplot在时间序列中绘制多条趋势线(每十年一条)。

以下是数据:

dat <- structure(list(YY = 1961:2010, a = c(98L, 76L, 83L, 89L, 120L, 
107L, 83L, 83L, 92L, 104L, 98L, 91L, 81L, 69L, 86L, 76L, 85L, 
86L, 70L, 81L, 77L, 89L, 60L, 80L, 94L, 66L, 77L, 85L, 77L, 80L, 
79L, 79L, 65L, 70L, 80L, 87L, 84L, 67L, 106L, 129L, 95L, 79L, 
67L, 105L, 118L, 85L, 86L, 103L, 97L, 106L)), .Names = c("YY", 
"a"), row.names = c(NA, -50L), class = "data.frame")

以下是脚本:

这里是脚本:

p <- ggplot(dat, aes(x = YY))
p <- p + geom_line(aes(y=a),colour="blue",lwd=1)
p <- p + geom_point(aes(y=a),colour="blue",size=2)

p <- p + theme(panel.background=element_rect(fill="white"),
         plot.margin = unit(c(0.5,0.5,0.5,0.5),"cm"),
         panel.border=element_rect(colour="black",fill=NA,size=1),
         axis.line.x=element_line(colour="black"),
         axis.line.y=element_line(colour="black"),
         axis.text=element_text(size=15,colour="black",family="serif"),
         axis.title=element_text(size=15,colour="black",family="serif"),
         legend.position = "top")

p <- p + scale_x_discrete(limits = c(seq(1961,2010,5)),expand=c(0,0))

p <- p + geom_smooth(data=dat[1:10,],aes(x=YY,y=a),method="lm",se=FALSE,color="black",formula=y~x,linetype="dashed")

p <- p + geom_smooth(data=dat[11:20,],aes(x=YY,y=a),method="lm",se=FALSE,color="black",formula=y~x,linetype="dashed")

p <- p + geom_smooth(data=dat[21:30,],aes(x=YY,y=a),method="lm",se=FALSE,color="black",formula=y~x,linetype="dashed")

p <- p + geom_smooth(data=dat[31:40,],aes(x=YY,y=a),method="lm",se=FALSE,color="black",formula=y~x,linetype="dashed")

p <- p + geom_smooth(data=dat[41:50,],aes(x=YY,y=a),method="lm",se=FALSE,color="black",formula=y~x,linetype="dashed")

p <- p + labs(x="Year",y="Number of Days")
outImg <- paste0("test",".png")
ggsave(outImg,p,width=8,height=5)

以下是生成的图片:

输出图片

我的需求/问题

  1. 我想提取斜率并将其添加到图中的趋势线上。如何从geom_smooth()中提取每条线的斜率?

  2. 目前,我正在逐个绘制趋势线。我想知道是否有一种有效的方法可以进行可调节时间窗口的操作。例如,假设我想为每5年绘制一次趋势线。在上面的图中,时间窗口为10。

  3. 假设我仅想绘制显著的趋势线(即p值<0.05,null:无趋势或斜率为0),是否可以使用geom_smooth()实现这一点?

非常感谢您的帮助。

1个回答

8
因此,在将数据传输到ggplot2之前,最好处理这些任务中的每一个,但是使用tidyverse中的其他软件包可以使所有这些任务变得相当容易。
从问题1和2开始:
虽然ggplot2可以绘制回归线,但要提取估计的斜率系数,您需要明确使用lm()对象。使用group_by()和mutate(),您可以添加分组变量(我的代码仅为5年组添加了此变量,仅作为示例),然后仅在现有数据框的列中计算并提取斜率估计。然后,可以使用geom_text()调用在ggplot中绘制这些斜率估计值。我以下以一种快速且不太规范的方式完成了此操作(将每个标签放置在它们回归的x和y值的平均值处),但您可以在数据框中指定它们的确切位置。
分组变量和数据准备也使问题2变得轻松:现在,您已经在数据框中明确了分组变量,因此没有必要逐个绘制,geom_smooth()接受group美学。
此外,要回答问题3,您可以从lm对象的摘要中提取pvalue,并过滤出仅对您关心的级别显着的内容。如果将此现在完整的数据框传递给geom_smooth()和geom_text(),您将获得所需的情节!
library(tidyverse)

 # set up our base plot
 p <- ggplot(dat, aes(x = YY, y = a)) +
  geom_line(colour = "blue", lwd = 1) +
  geom_point(colour = "blue", size = 2) +
  theme(
    panel.background = element_rect(fill = "white"),
    plot.margin = unit(c(0.5, 0.5, 0.5, 0.5), "cm"),
    panel.border = element_rect(colour = "black", fill = NA, size = 1),
    axis.line.x = element_line(colour = "black"),
    axis.line.y = element_line(colour = "black"),
    axis.text = element_text(size = 15, colour = "black", family = "serif"),
    axis.title = element_text(size = 15, colour = "black", family = "serif"),
    legend.position = "top"
  ) +
  scale_x_discrete(limits = c(seq(1961, 2010, 5)), expand = c(0, 0))

# add a grouping variable (or many!)
 prep5 <- dat %>%
  mutate(group5 = rep(1:10, each = 5)) %>%
  group_by(group5) %>%
  mutate(
    slope = round(lm(YY ~ a)$coefficients[2], 2),
    significance = summary(lm(YY ~ a))$coefficients[2, 4],
    x = mean(YY),   # x coordinate for slope label
    y = mean(a)     # y coordinate for slope label
  ) %>%
  filter(significance < .2)   # only keep those with a pvalue < .2 

p + geom_smooth(
  data = prep5, aes(x = YY, y = a, group = group5),  # grouping variable does the plots for us!
  method = "lm", se = FALSE, color = "black",
  formula = y ~ x, linetype = "dashed"
) +
  geom_text(
    data = prep5, aes(x = x, y = y, label = slope),
    nudge_y = 12, nudge_x = -1
  )

现在,您可能需要更加小心地指定文本标签的位置,而不是像我这里一样。我使用了means和geom_text()nudge_*参数来进行快速示例,但请记住,由于这些值显式映射到x和y坐标,您拥有完全控制权!

此文档创建于2018-07-16,使用了reprex包 (v0.2.0)。


哇!这太棒了。在绘图之前,我实际上是单独计算显著趋势的,而我的代码很混乱,所以我没有在我的帖子中包含它。非常感谢你! - Lyndz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接