代码之家  ›  专栏  ›  技术社区  ›  Emma Wiik

更改ggplot2中条形图的打印顺序

  •  2
  • Emma Wiik  · 技术社区  · 6 年前

    我正在为修改后的手稿准备一个附录图,其中我需要提供年份和地点之间几个变量的年内范围(可变性)的信息。

    我想出了最整洁的方法(我有7个网站,21年,5个变量…)将使用玫瑰图 coord_polar . 然而,我偶然发现了一些令我一直对ggplot感到沮丧的东西——默认的排序假设。虽然因子很容易根据某个值重新排序,但这似乎只适用于 固定的 时尚:据我所知,订单需要应用于整个数据框架。

    在该图中,排序需要取决于年与年之间变化的值,因此 colour fill 值需要在面板内按打印顺序更改。

    为了演示,我创建了一个可复制的示例,代码如下(以不应该工作的方式绘制) example of wrong ordering

    基本上,我总是需要首先绘制给定年份内具有最小值的场地(中间),然后向外绘制其他场地的增值,按照原值的顺序(参见 order diff 数据框的列)。换句话说,有些年站点a将处于中心位置,有些年站点c将处于中心位置,等等。

    任何帮助都将不胜感激。

    library('ggplot2')
    library('reshape2')
    library("plyr")
    
    ## reproducible example of problem: create dummy data
    madeup <- data.frame(Year = rep(2000:2015, each=20), Site=rep(c("a","b","c","d"), each=5, times=16),
                         var1 = rnorm(n=16*20, mean=20, sd=5), var2= rnorm(n=16*20, mean=50, sd=1))
    
    ## create ranges of the data by Year and Site
    myRange <- function(dat) {range=max(dat, na.rm=TRUE)-min(dat,na.rm = TRUE)}
    vardf <- ddply(madeup, .(Site, Year), summarise, var1=myRange(var1),
                   var2=myRange(var2))
    
    varmelt <- melt(vardf, id.vars = c("Site","Year"))
    varmelt$Site <- as.character(varmelt$Site) # this to preserve the new order when rbind called
    varmelt <- by(varmelt, list(varmelt$Year, varmelt$variable), function(x) {x <- x[order(x$value),]
    x$order <- 1:nrow(x)
    return(x)})
    varmelt <- do.call(rbind, varmelt)
    
    ## create difference between these values so that each site gets plotted cumulatively on the rose plot
    ##  (otherwise areas close to the centre become uninterpretable)
    vartest <- by(varmelt, list(varmelt$Year, varmelt$variable), function(x) {
      x$diff <- c(x$value[1], diff(x$value))
      return(x)
    })
    vartest <- do.call(rbind,vartest)
    
    ## plot rose plot to display how ranges in variables vary by year and between sites
    ## for this test example we'll just take one variable, but the idea is to facet by variable
    max1 <- max(vartest$value[vartest$variable=='var1'])
    yearlength <- length(2000:2015)
    ggplot(vartest[vartest$variable=="var1",], aes(x=factor(Year), y=diff)) +
      theme_bw() +
      geom_hline(yintercept = seq(0,max1, by=1), size=0.3, col="grey60",lty=3) +
      geom_vline(xintercept=seq(1,yearlength,1), size=0.3, col='grey30', lty=2) +
      geom_bar(stat='identity', width=1, size=0.5, aes(col=Site, fill=Site)) +
      scale_x_discrete() +
      coord_polar() +
      theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Mikko Marttila    6 年前

    只要不使用堆叠的钢筋( position = "stack" ,这是的默认值 geom_bar ), ggplot2 实际上会 use the order of the rows in your data for the plotting order . 因此,您只需使用y轴的原始值(而不是累积差分值)以及 position = "identity" 按从大到小的顺序排列数据 value 打印前 :

    ordered_data <- vartest[order(-vartest$value), ]
    
    ggplot(ordered_data, aes(factor(Year), value)) +
      geom_col(aes(fill = Site), position = "identity", width = 1) +
      coord_polar() +
      facet_wrap(~ variable)
    

    于2018年2月17日由 reprex package (v0.2.0)。

    PS.在生成示例的随机数据时,请考虑使用 set.seed 这样就可以准确地再现您的结果。

        2
  •  1
  •   Community T.Woody    4 年前

    您可以从最大站点的单个绘图开始,然后在顶部分层较小的站点,如下所示:

    a <- ggplot(vartest[vartest$variable=="var1"& vartest$order==4,], aes(x=factor(Year), y=value,group=order)) +
      theme_bw() +
      geom_hline(yintercept = seq(0,max1, by=1), size=0.3, col="grey60",lty=3) +
      geom_vline(xintercept=seq(1,yearlength,1), size=0.3, col='grey30', lty=2) +
      geom_bar(stat='identity', width=1, size=0.5, aes(col=Site, fill=Site)) +
      scale_x_discrete() +
      coord_polar() +
      theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
    
    b <- a + geom_bar(data = vartest[vartest$variable=="var1"& vartest$order==3,],
                stat='identity', width=1, size=0.5, aes(x=factor(Year), y=value,col=Site, fill=Site))
    
    c <- b + geom_bar(data = vartest[vartest$variable=="var1"& vartest$order==2,],
                stat='identity', width=1, size=0.5, aes(x=factor(Year), y=value,col=Site, fill=Site))
    
    c + geom_bar(data = vartest[vartest$variable=="var1"& vartest$order==1,],
                stat='identity', width=1, size=0.5, aes(x=factor(Year), y=value,col=Site, fill=Site))
    

    这将产生以下结果: stacked plot

    这就是你想要的吗?