Add directlabels to geom_smooth rather than geom_line

好久不见. 提交于 2019-12-07 13:01:07

问题


I recognize that this question is a close duplicate of this one, but the solution there no longer works (using method="last.qp"), so I'm asking it again.

The basic issue is that I'd like to use directlabels (or equivalent) to label smoothed means for each group (from stat_smooth()), rather than the actual data. The example below shows as close as I've gotten, but the labels aren't recognizing the grouping, or even the smoothed line. Instead, I'm getting the label at the last point. What I'd like is colour-coordinated text at the end of each smoothed line, rather than the legend on the right of the plot.

Here's an example:

library(ggplot2)
library(directlabels)

## Data
set.seed(10)
d <- data.frame(x=seq(1,100,1), y=rnorm(100, 3, 0.5))
d$z <- ifelse(d$y>3,1,0)

## Plot
p <- ggplot(d, aes(x=x, y=y, colour=as.factor(z))) +
  stat_smooth(inherit.aes=T, se=F, span=0.8, show.legend = T) +
  geom_line(colour="grey50") +
  scale_x_continuous(limits=c(0,110)) +
  geom_dl(label="text", method="maxvar.points", inherit.aes=T)
p

which makes this plot:


回答1:


A solution using ggrepel package based on this answer

library(tidyverse)
library(ggrepel)

set.seed(123456789)

d <- data.frame(x = seq(1, 100, 1), y = rnorm(100, 3, 0.5))
d$z <- ifelse(d$y > 3, 1, 0)

labelInfo <-
  split(d, d$z) %>%
  lapply(function(t) {
    data.frame(
      predAtMax = loess(y ~ x, span = 0.8, data = t) %>%
        predict(newdata = data.frame(x = max(t$x)))
      , max = max(t$x)
    )}) %>%
  bind_rows

labelInfo$label = levels(factor(d$z))
labelInfo

#>   predAtMax max label
#> 1  2.538433  99     0
#> 2  3.293859 100     1

ggplot(d, aes(x = x, y = y, color = factor(z))) + 
  geom_point(shape = 1) +
  geom_line(colour = "grey50") +
  stat_smooth(inherit.aes = TRUE, se = FALSE, span = 0.8, show.legend = TRUE) +
  geom_label_repel(data = labelInfo, 
                   aes(x = max, y = predAtMax, 
                       label = label, 
                       color = label), 
                   nudge_x = 5) +
  theme_classic()
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Created on 2018-06-11 by the reprex package (v0.2.0).




回答2:


You need to tell geom_dl what you want to appear on you plot. The code below should simply address your needs;

p <- ggplot(d, aes(x=x, y=y, colour=as.factor(z))) +
  stat_smooth(inherit.aes=T, se=F, span=0.8, method = "loess", show.legend = F) +
  geom_line(colour="grey50") +
  scale_x_continuous(limits=c(0,110)) +
  geom_dl(label=as.factor(d$z), method="maxvar.points", inherit.aes=T)

If you want different text rather than 0 and 1 you just need to make it based on d$z and put that instead of as.factor(d$z).

In order to put the labels beside last point of geom_smooth rather than last datapoints, I could not find any of the method in geom_dl to do so, therefore, came up with a workaround:

p <- ggplot(d, aes(x=x, y=y, colour=as.factor(z))) +
  stat_smooth(inherit.aes=T, aes(label=as.factor(z)), se=F, 
              span=0.8, method = "loess", show.legend = F) +
  geom_line(colour="grey50") +
  scale_x_continuous(limits=c(0,110))


library(data.table)
smooth_dat <- setDT(ggplot_build(p)$data[[1]])
smooth_lab <- smooth_dat[smooth_dat[, .I[x == max(x)], by=group]$V1]


p + annotate("text", x = smooth_lab$x, y=smooth_lab$y, 
             label=smooth_lab$label,colour=smooth_lab$colour,
             hjust=-1)



来源:https://stackoverflow.com/questions/50806603/add-directlabels-to-geom-smooth-rather-than-geom-line

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!