【问题标题】:ggplot2: Make multiple line+ribbon's with legendggplot2:用图例制作多行+丝带
【发布时间】:2020-10-16 14:27:01
【问题描述】:

我想在 ggplot2 中使用

  • 多行,
  • 每个都有一个环绕的丝带,
  • 具有用户指定的颜色,
  • 并带有显示线条颜色和色带颜色的图例。

(向下滚动以查看几乎达到我所寻求的情节的示例。) 我已经看到了相关的问题,但没有一个可以同时解决所有这些问题,而且我在网上查找了示例,但找不到这样的示例。我是 ggplot2 的新手,所以为这样一个基本问题道歉,但也许你的回答也会对其他人有所帮助。

这是一个非常不雅的尝试拼凑一个几乎完成我想要的图表的完整示例。我尝试过使用宽格式数据和长格式数据。 (是的,我使用= 而不是<-,并且我不使用许多人推荐的空格,但这些是单独的问题...... :-)

# Housekeeping:
graphics.off()
library("ggplot2")
library("tidyr") # for pivot_longer()

# Set up data:
set.seed(47405)
x = 1:10
y1 = 1 + 0.1*x + rnorm(length(x),0,0.2)  # line 1
y2 = 2 + 0.2*x + rnorm(length(x),0,0.2)  # line 2
y1lo = y1 - 0.2  # ribbon 1 low
y1hi = y1 + 0.2  # ribbon 1 high
y2lo = y2 - 0.3  # ribbon 2 low
y2hi = y2 + 0.3  # ribbon 2 high

# Wide format data frame:
wideDF = data.frame( x=x , 
                     y1lo=y1lo , y1=y1 , y1hi=y1hi ,
                     y2lo=y2lo , y2=y2 , y2hi=y2hi )

# Long format data frame:
longDF = pivot_longer( wideDF , cols=!x , names_to="line" , values_to="y" )
longDF$fill = NA
longDF$fill[grep( "1" , longDF$line  )] = "y1"
longDF$fill[grep( "2" , longDF$line  )] = "y2"

使用宽格式的不雅方式,但没有图例:

ggplot( wideDF , aes(x=x) ) +
  geom_ribbon( aes( ymin=y1lo , ymax=y1hi ) , fill="pink" , alpha=0.5 ) +
  geom_line( aes( y=y1 ) , col="red" ) +
  geom_ribbon( aes( ymin=y2lo , ymax=y2hi ) , fill="lightblue" , alpha=0.5 ) +
  geom_line( aes( y=y2 ) , col="blue" ) +
  labs( title="Using WIDE data frame" , y="Y label" , x="X label" ) +
  geom_text( x = max(wideDF$x) , 
             y = wideDF$y1[wideDF$x==max(wideDF$x)] ,
             hjust = 1 , vjust = -0.5 , 
             label="Y1" , color = "red" ) +
  geom_text( x = max(wideDF$x) , 
             y = wideDF$y2[wideDF$x==max(wideDF$x)] , 
             hjust = 1 , vjust = -0.5 , 
             label="Y2" , color = "blue" )

使用长格式的不雅方式,仍然没有图例:

ggplot( ) + 
  xlim(range(longDF$x)) + ylim(range(longDF$y)) +
  geom_ribbon( aes( x=longDF$x[longDF$line=="y1"] ,
                    ymin=longDF$y[longDF$line=="y1lo"] ,
                    ymax=longDF$y[longDF$line=="y1hi"] ), 
               fill="pink" , alpha=0.5  ) +
  geom_line( aes( x=longDF$x[longDF$line=="y1"] ,
                  y=longDF$y[longDF$line=="y1"] ) ,
             color="red" ) +
  geom_ribbon( aes( x=longDF$x[longDF$line=="y2"] ,
                    ymin=longDF$y[longDF$line=="y2lo"] ,
                    ymax=longDF$y[longDF$line=="y2hi"] ), 
               fill="lightblue" , alpha=0.5  ) +
  geom_line( aes( x=longDF$x[longDF$line=="y2"] ,
                  y=longDF$y[longDF$line=="y2"] ) ,
             color="blue" ) +
  labs( title="Using LONG data frame" , y="Y label" , x="X label" ) +
  geom_text( aes(
             x = max(longDF$x) , 
             y = longDF$y[longDF$x==max(longDF$x) & longDF$line=="y1"] ) ,
             hjust = 1 , vjust = -0.5 , 
             label="Y1" , color = "red" ) +
  geom_text( aes( x = max(longDF$x) ,
             y = longDF$y[longDF$x==max(longDF$x) & longDF$line=="y2"] ) ,
             hjust = 1 , vjust = -0.5 ,
             label="Y2" , color = "blue" )

所以,我的问题:

  1. 多条线+带状图如何编码高效?上面的代码非常不优雅,我显然在 ggplot2 中缺少关于 aes()data= 的基本概念。不仅显示代码而且简要解释aes() 发生了什么的答案会很棒。

  2. 如何在这些图中添加图例? (当然,有了图例,就不需要上面例子中的 geom_text() 元素了。)

  3. 对于ggplot中的多条线+带状图,宽格式或长格式数据框更有用吗?

谢谢!

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    也许这就是你要找的……

    1. 一般课程:如果你想要一个图例,你必须在美学上映射一些东西,即将color 和/或fill 放在aes()

    2. 无论是宽数据集还是长数据集都不适合轻松绘制。相反,从你的长 df 开始,我首先去掉你行列中的数字并使数据集更宽,所以我们只有yyminymax(这样做之后,我们得到了整洁的数据,因为 1 和 2 是一个变量的类别,而 y、ymin、ymax 是不同的变量)。这使我们可以仅使用两个几何图层设置您的绘图。此外,我们不必使用复杂且容易出错的代码(如 longDF$x[longDF$line=="y2"])来获取我们想要绘制的值。

    3. 对于文本标签,我使用group_by(longDF1, fill) %>% top_n(1, x) 作为数据,它只是为每行选取具有最高 x 值的行。

    4. 最后,通过scale_xxx_manual 设置正确的颜色

    library(dplyr)
    library("ggplot2")
    library("tidyr") # for pivot_longer()
    
    # Set up data:
    set.seed(47405)
    x = 1:10
    y1 = 1 + 0.1*x + rnorm(length(x),0,0.2)  # line 1
    y2 = 2 + 0.2*x + rnorm(length(x),0,0.2)  # line 2
    y1lo = y1 - 0.2  # ribbon 1 low
    y1hi = y1 + 0.2  # ribbon 1 high
    y2lo = y2 - 0.3  # ribbon 2 low
    y2hi = y2 + 0.3  # ribbon 2 high
    
    # Wide format data frame:
    wideDF = data.frame( x=x , 
                         y1lo=y1lo , y1=y1 , y1hi=y1hi ,
                         y2lo=y2lo , y2=y2 , y2hi=y2hi )
    
    # Long format data frame:
    longDF = pivot_longer( wideDF , cols=!x , names_to="line" , values_to="y" )
    longDF$fill = NA
    longDF$fill[grep( "1" , longDF$line  )] = "y1"
    longDF$fill[grep( "2" , longDF$line  )] = "y2"
    
    longDF1 <- longDF %>% 
      mutate(line = gsub("\\d", "", line)) %>% 
      pivot_wider(id_cols = c(x, fill), names_from = line, values_from = y)
    
    ggplot(longDF1) +
      geom_ribbon(aes(x=x, ymin=ylo, ymax=yhi, fill = fill), alpha=0.5) +
      geom_line(aes(x=x, y=y, color = fill)) +
      labs( title="Using LONG data frame" , y="Y label" , x="X label" ) +
      geom_text(data = group_by(longDF1, fill) %>% top_n(1, x), 
                aes(x = x, y = y, label = toupper(fill), color = fill), 
                hjust = 1 , vjust = -0.5, show.legend = FALSE) +
      scale_color_manual(values = c(y1 = "red", y2 = "blue")) + 
      scale_fill_manual(values = c(y1 = "pink", y2 = "lightblue"))
    

    【讨论】:

    • 精彩的答案。清楚地解释了数据框的关键格式,以及在aes() 中包含fill=color= 的关键。还有手动颜色设置。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 2016-10-20
    • 2018-11-12
    相关资源
    最近更新 更多