【问题标题】:Plotting continuous and discrete series in ggplot with facet在带有 facet 的 ggplot 中绘制连续和离散序列
【发布时间】:2013-04-14 12:58:16
【问题描述】:

我有四个不同变量随时间变化的数据。我想使用 facet_grid 将它们组合在一个图中,其中每个变量都有自己的子图。以下代码类似于我的数据和我呈现它的方式:

require(ggplot2)
require(reshape2)

subm <- melt(economics, id='date', c('psavert','uempmed','unemploy'))
mcsm <- melt(data.frame(date=economics$date, q=quarters(economics$date)), id='date')
mcsm$value <- factor(mcsm$value)


ggplot(subm, aes(date, value, col=variable, group=1)) + geom_line() + 
       facet_grid(variable~., scale='free_y') + 
       geom_step(data=mcsm, aes(date, value)) + 
       scale_y_discrete(breaks=levels(mcsm$value))

如果我忽略 scale_y_discrete,R 会抱怨我正在尝试将离散值与连续比例相结合。如果我包含 scale_y_discreate 我的连续系列会错过它们的比例。

有没有什么巧妙的方法来解决这个问题,即。让所有秤都正确吗?我还看到图例是按字母顺序排序的,我可以更改它,使图例按照与子图相同的顺序排列吗?

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    您的数据存在问题,对于数据框 subm value 是数字(连续),但对于 mcsm value 是因子(离散)。您不能对数值和连续值使用相同的比例,并且您只能获得最后一个方面(离散)的 y 值。此外,不可能在一个绘图中使用两个 scale_y...() 函数。

    我的方法是将 mcsm value 设为数字(另存为 value2)然后使用它们 - 它将四分之一绘制为 1、2、3 和 4。要解决图例问题,请使用scale_color_discrete() 并根据需要提供breaks=

    mcsm$value2<-as.numeric(mcsm$value)
    ggplot(subm, aes(date, value, col=variable, group=1)) + geom_line()+
     facet_grid(variable~., scale='free_y') + geom_step(data=mcsm, aes(date, value2)) +
      scale_color_discrete(breaks=c('psavert','uempmed','unemploy','q'))
    

    更新 - 使用 grobs 的解决方案

    另一种方法是使用 grobs 和库 gridExtra 将数据绘制为单独的图。

    首先,将带有所有图例和数据(代码如上)的图保存为对象p。然后使用函数ggplot_build()ggplot_gtable() 将绘图保存为grob 对象gp。从 gp 中提取仅绘制图例的部分(保存为对象 gp.leg) - 在这种情况下是列表元素编号 17。

    library(gridExtra)
    p<-ggplot(subm, aes(date, value, col=variable, group=1)) + geom_line()+
      facet_grid(variable~., scale='free_y') + geom_step(data=mcsm, aes(date, value2)) +
      scale_color_discrete(breaks=c('psavert','uempmed','unemploy','q'))
    gp<-ggplot_gtable(ggplot_build(p))
    gp.leg<-gp$grobs[[17]]
    

    制作两个新图 p1p2 - 首先绘制 subm 的数据,第二个绘制 mcsm 的数据。使用scale_color_manual() 设置与绘图p 相同的颜色。对于第一个绘图,删除 x 轴标题、文本和刻度,并使用 plot.margin= 将下边距设置为负数。对于第二个图,将上边距更改为负数。 faced_grid() 应该用于两个图以获得多面外观。

    p1 <- ggplot(subm, aes(date, value, col=variable, group=1)) + geom_line()+
       facet_grid(variable~., scale='free_y')+
      theme(plot.margin = unit(c(0.5,0.5,-0.25,0.5), "lines"),
            axis.text.x=element_blank(),
            axis.title.x=element_blank(),
            axis.ticks.x=element_blank())+
      scale_color_manual(values=c("#F8766D","#00BFC4","#C77CFF"),guide="none")
    
    p2 <- ggplot(data=mcsm, aes(date, value,group=1,col=variable)) + geom_step() +
      facet_grid(variable~., scale='free_y')+
      theme(plot.margin = unit(c(-0.25,0.5,0.5,0.5), "lines"))+ylab("")+
      scale_color_manual(values="#7CAE00",guide="none")
    

    将两个图 p1p2 保存为 grob 对象,然后为两个图设置相同的宽度。

    gp1 <- ggplot_gtable(ggplot_build(p1))
    gp2 <- ggplot_gtable(ggplot_build(p2))
    maxWidth = grid::unit.pmax(gp1$widths[2:3],gp2$widths[2:3])
    gp1$widths[2:3] <- as.list(maxWidth)
    gp2$widths[2:3] <- as.list(maxWidth)
    

    使用函数grid.arrange()arrangeGrob() 将绘图和图例安排在一个绘图中。

    grid.arrange(arrangeGrob(arrangeGrob(gp1,gp2,heights=c(3/4,1/4),ncol=1),
           gp.leg,widths=c(7/8,1/8),ncol=2))
    

    【讨论】:

    • 我乐观地希望我能够将这两种类型结合起来,就像我期望的那样,在第四张图上使用无法用数字表示的数据。感谢您的回答!
    • @sgunnars 添加了解决方案,为您提供两种数据类型的表示。
    • 很高兴看到它是可能的。在我拥有的数据中,有两件事我没有到位。首先,我收到有关 gp.leg 的投诉。其次,连续函数和离散函数在 x 轴上略有不同。 maxWidth = grid::unit.pmax(gp1$widths[2:3],gp2$widths[2:3]) 不是要处理这个吗?如果是这样,它对我不起作用。
    • maxWidth 线使两个图的宽度相同,但不会更改轴值 - 您应该尝试使两个图中的比例相同。对于 gp.leg - 查看对象 gp 并查看“引导框”位于哪一行(在每种情况下都不会是第 17 行)
    • 我误解了第一位,因此没有使用它。感谢您提供非常好的答案。
    猜你喜欢
    • 2012-07-15
    • 2020-09-04
    • 2018-03-21
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 2015-04-22
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多