【问题标题】:Program labels on line graph to avoid line ggplot2折线图上的程序标签以避免直线ggplot2
【发布时间】:2017-09-13 14:33:20
【问题描述】:

我很好奇是否有办法在 ggplot2 的折线图上叠加标签以避免穿过这条线。我使用了 vjust,它在大多数情况下都有效,但是当两个日期之间有较大的增加或减少时,这条线会穿过标签,使其难以阅读。我将把我目前正在使用的情节和代码放在下面。在这种情况下,我想移动 920; 1,467;和 1,480 人下线。我正在通过 Reporters 包将绘图导出到 powerpoint,所以我可以手动移动它,我只是想知道是否有办法避免这种情况。

剧情:

代码:

library("ggplot2")
library("scales")

line_data <- c(276, 475, 753, 840, 931, 962, 801, 920, 1467, 1840, 1737, 1638, 1789, 1733, 1480, 1464, 1538)
year_data <- c(2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
               2017)

line_data_total <- as.data.frame(cbind(line_data, year_data))

limit_func <- function(x) {
  if (nchar(max(x)) == 2){
    round(max(x +5), digits = -1)
  } else if (nchar(max(x)) == 3){
    round(max(x +50), digits = -2)
  } else if (nchar(max(x)) == 4){
    round(max(x +500), digits = -3)
  }
}

ggplot(data = line_data_total, aes(x = year_data, y = line_data, group = 1)) +
  geom_line(color = "red", size = 1.2)+
  geom_point(color = "red", fill = "red", shape = 23, size = 1.75) +
  geom_text(aes(label = paste0(format(round(as.numeric(line_data), 1), nsmall = 0, big.mark = ","))),
            size = 3, fontface = "bold", vjust = -2) +
  labs(x = '', y = '') +
  expand_limits(y = c(0, limit_func(line_data_total$line_data))) +
  scale_x_continuous(breaks = seq(min(line_data_total$year_data), max(line_data_total$year_data), 1)) +
  scale_y_continuous(labels = comma) +
  theme(panel.grid.major.x = element_blank() ,
        panel.grid.major.y = element_line( size=.1, color="light gray"),
        panel.background = element_rect(fill = "transparent"),
        plot.background = element_rect(fill = "transparent"),
        axis.text.x = element_text(face = "bold", size = 10),
        axis.text.y = element_text(face = "bold", size = 10),
        axis.ticks.y = element_blank())

【问题讨论】:

  • 如果其中一个答案解决了您的问题,您应该用复选标记将其标记为最佳答案。

标签: r plot ggplot2 linegraph


【解决方案1】:

如何使用ggplot2 扩展ggrepel

require(ggrepel)

将您的 geom_text() 行替换为:

geom_text_repel(aes(label = paste0(format(round(as.numeric(line_data), 1), nsmall = 0, big.mark = ","))),
            size = 3, fontface = "bold", nudge_y=150)

nudge_y 是使标签下线的原因,您可以使用nudge_xnudge_y 的组合来获得更多控制。并查看包小插曲:https://github.com/slowkow/ggrepel/blob/master/vignettes/ggrepel.md

【讨论】:

    【解决方案2】:

    在不摆弄geom_text_repel 的设置的情况下,我想尝试一个针对这样的时间序列通用的解决方案。我编写了一个函数,它查看两个 x 相邻点并计算它们之间的斜率,以及中间点是更低、更高还是在 y 中的 x 相邻点之间强>方向。

    • 如果一个点在其 x 相邻点之间是 y-,则标签将沿对角线移动,远离连接它们的直线的斜率。
    • 如果该点位于其 x 相邻点的 y 之下,则标签居中,但向下移动。
    • 如果该点位于其 x 邻居之上的 y,则标签居中,但向上移动。

    library(dplyr)
    
    adjust_away_from_line <- function(df, x, y, vextend = 0.5) {
      if(!is.data.frame(df)) {return(df)}
    
      x <- enquo(x)
      y <- enquo(y)
    
      if(!(quo_name(x) %in% names(df))) {
        warning(paste0("Column '", quo_name(x), "' not found in data."))
        return(df)
      }
    
      if(!(quo_name(y) %in% names(df))) {
        warning(paste0("Column '", quo_name(y), "' not found in data."))
        return(df)
      }
    
    
      df %>% arrange(!!x) %>% 
        mutate(nb.slope = case_when(
          is.na(lead(!!y)) ~ (    (!!y) - lag(!!y))/(    (!!x) - lag(!!x)),
          is.na(lag(!!y))  ~ (lead(!!y) -    (!!y))/(lead(!!x) -    (!!x)),
          TRUE             ~ (lead(!!y) - lag(!!y))/(lead(!!x) - lag(!!x))  
        ),
        nb.pos = case_when(
          is.na(lead(!!y))                              ~ -sign(nb.slope),
          is.na(lag(!!y))                               ~ -sign(nb.slope),
           (lead(!!y) >= (!!y)) &  (lag(!!y) >= (!!y))  ~  1.1,
          !(lead(!!y) >= (!!y)) & !(lag(!!y) >= (!!y))  ~ -1.1,
          TRUE                                          ~ -1
        ),
        hjust = case_when(
          nb.pos   >  1 ~ 0.5,
          nb.pos   < -1 ~ 0.5,
          nb.slope >  0 ~ 1,
          nb.slope <  0 ~ 0,
          TRUE          ~ 0.5
        ),
        vjust = scales::rescale(round(nb.pos), to = c(0-vextend, 1+vextend))) %>% 
        select(-nb.slope, -nb.pos)
    
    
    }
    

    由于它将数据框作为第一个参数,因此您可以在管道中使用此函数,按顺序为其提供 x 变量和 y 变量的裸名:

    data.frame(line_data = c(276, 475, 753, 840, 931, 962, 801, 920, 1467, 
                             1840, 1737, 1638, 1789, 1733, 1480, 1464, 1538),
               year_data = c(2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 
                             2011, 2012, 2013, 2014, 2015, 2016, 2017)
               ) %>%
      adjust_away_from_line(year_data, line_data) %>%
      ggplot(aes(year_data, line_data)) +
      geom_line() + 
      geom_point() +
      geom_text(aes(label = line_data, hjust = hjust, vjust = vjust))
    

    如果您想将标签进一步上下移动,远离线条,您可以使用adjust_away_from_line(..., vextend = ##) 参数来实现。默认值为 0.5,但在不同的应用程序中您可能需要 0.75 或 1。

    【讨论】:

      猜你喜欢
      • 2018-03-21
      • 1970-01-01
      • 1970-01-01
      • 2016-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      • 1970-01-01
      相关资源
      最近更新 更多