【问题标题】:How to plot a horizontal number line with ggplot, having 0 at the center?如何用ggplot绘制水平数轴,中心为0?
【发布时间】:2021-05-25 14:57:06
【问题描述】:

我正在尝试使用ggplot2 绘制一条中心为 0 的水平数轴,以比较沿该轴的不同项目。

示例

假设我们对不同老鼠的饮食产生的影响感兴趣。每只老鼠喂食不同类型的食物,一个月后,我们比较老鼠的体重。对于每只老鼠,我们想知道体重是增加还是减少,以及减少了多少。

library(dplyr)

df <- 
  data.frame(mouse = c("Mickey", "Jerry", "Gonzales", "Remi"),
           weight_pre = c(10.1, 6.2, 9.5, 13.3),
           weight_post = c(9.2, 12.4, 2.3, 10)) 


df_with_diff <-
  df %>%
  mutate(diff = weight_post - weight_pre)


df_with_diff
#>      mouse weight_pre weight_post diff
#> 1   Mickey       10.1         9.2 -0.9
#> 2    Jerry        6.2        12.4  6.2
#> 3 Gonzales        9.5         2.3 -7.2
#> 4     Remi       13.3        10.0 -3.3

reprex package (v2.0.0) 于 2021-05-25 创建

期望的输出

我正在尝试实现一个简单的水平数字线,如下图所示,中心为 0: (显然这不是按比例绘制的,只是为了表明我的意图)

知道如何使用ggplot 执行此操作(或足够接近的操作)吗?

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    我会使用pointrangetheme_minimal。例如:

    library(ggplot2)
    library(dplyr)
    library(ggrepel)
    
    df_with_diff %>%
            mutate(min = ifelse(diff > 0, 0, diff),
                   max = ifelse(diff > 0, diff, 0)) %>%
            ggplot(aes(x = diff, y = mouse, col = mouse, label = diff)) +
            geom_pointrange(aes(xmin = min, xmax = max)) +
            geom_text_repel() +
            theme_minimal() +
            theme(panel.grid.major.x = element_blank(),
                  panel.grid.minor.x = element_blank(),
                  legend.position = "none")
    

    【讨论】:

    • 谢谢!您介意解释一下使用mutate()ifelse() 创建minmax 的步骤吗?我不完全理解这一点,而且这个解决方案似乎很重要。
    • @Emman 当然! :) geom_pointrange 需要每个 lineminmax 被绘制。我使用ifelse 创建了新变量,其中包含要绘制的线的maxmin 值。这些新变量控制您的lines 开始和结束的位置。您还可以手动为每个line 提供xminxmax 点作为vector(在这种情况下为4)
    【解决方案2】:

    要概述您可以使用哪些工具以及它们的工作原理,请查看此代码

    #Draw horizontal lines and set up plot
    maxAbsDiff <- max(abs(df_with_diff$diff))
    xLimits <- c(-2*maxAbsDiff,2*maxAbsDiff)
    p <- ggplot() + geom_hline(yintercept = 1:NROW(df_with_diff)) + geom_point(mapping = aes(x=0,y=1:NROW(df_with_diff))) +
      scale_x_continuous(limits = xLimits, expand=c(0,0)) + labs(x=NULL,y=NULL,title = NULL) + 
      scale_y_continuous(breaks = 1:NROW(df_with_diff), labels = df_with_diff$mouse)
    
    #Draw the lines decoding the diff
    lineData <- data.frame(xStart=rep(0,NROW(df_with_diff)), xEnd = df_with_diff$diff, 
                           yStart = 1:NROW(df_with_diff)+0.2, yEnd =1:NROW(df_with_diff)+0.2, 
                           col = paste0("something_",1:NROW(df_with_diff)))
    
    p <- p + geom_segment(data = lineData, mapping = aes(x=xStart,xend = xEnd, y = yStart, yend = yEnd, col = col))
    p <- p + theme(legend.position = "none")
    
    #Anotate with the diff-values
    annotationData <- data.frame(xpos = df_with_diff$diff/2, ypos = 1:NROW(df_with_diff)+0.5, lab = as.character(df_with_diff$diff))
    p <- p + annotate(geom = "text", x = annotationData$xpos, y = annotationData$ypos, label = annotationData$lab)
    

    生产

    它的样式不是你想要的,但是查看所用函数的文档,你应该很容易得到你想要的。要摆脱背景,请查看theme-function 的文档。我认为 ggplot 还提供了诸如空主题或空主题之类的东西,这样您就有了删除网格的快捷方式,而不是设置 theme 的所有参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-09
      • 2017-12-16
      相关资源
      最近更新 更多