【问题标题】:Gantt plot in base r - modifying plot properties基础 r 中的甘特图 - 修改绘图属性
【发布时间】:2014-10-15 04:07:05
【问题描述】:

我想问一个与这篇文章 [Gantt style time line plot (in base R)] 中给出的答案有关的后续问题,该问题是基于 r 的甘特图。我觉得这值得提出一个新问题,因为我认为这些情节具有广泛的吸引力。我也希望一个新问题能引起更多关注。我也觉得我需要比那个问题的 cmets 更多的空间来具体说明。

以下代码由@digEmAll 提供。它需要一个数据框,其中的列表示开始时间、结束时间和分组变量,并将其转换为甘特图。我稍微修改了 @digEmAll 的函数,以使甘特图中的条形图/线段彼此相邻,而不是有间隙。这里是:

plotGantt <- function(data, res.col='resources', 
                      start.col='start', end.col='end', res.colors=rainbow(30))
{
  #slightly enlarge Y axis margin to make space for labels
  op <- par('mar')
  par(mar = op + c(0,1.2,0,0)) 

  minval <- min(data[,start.col])
  maxval <- max(data[,end.col])

  res.colors <- rev(res.colors)
 resources <- sort(unique(data[,res.col]),decreasing=T)


  plot(c(minval,maxval),
       c(0.5,length(resources)+0.5),
       type='n', xlab='Duration',ylab=NA,yaxt='n' )
  axis(side=2,at=1:length(resources),labels=resources,las=1)
  for(i in 1:length(resources))
  {
    yTop <- i+0.5
    yBottom <- i-0.5
    subset <- data[data[,res.col] == resources[i],]
    for(r in 1:nrow(subset))
    {
      color <- res.colors[((i-1)%%length(res.colors))+1]
      start <- subset[r,start.col]
      end <- subset[r,end.col]
      rect(start,yBottom,end,yTop,col=color)
    }
  }
  par(op) # reset the plotting margins
}

以下是一些示例数据。你会注意到我有四个组 1-4。但是,并非所有数据帧都具有所有四个组。有的只有两个,有的只有三个。

mydf1 <- data.frame(startyear=2000:2009, endyear=2001:2010, group=c(1,1,1,1,2,2,2,1,1,1))
mydf2 <- data.frame(startyear=2000:2009, endyear=2001:2010, group=c(1,1,2,2,3,4,3,2,1,1))
mydf3 <- data.frame(startyear=2000:2009, endyear=2001:2010, group=c(4,4,4,4,4,4,3,2,3,3))
mydf4 <- data.frame(startyear=2000:2009, endyear=2001:2010, group=c(1,1,1,2,3,3,3,2,1,1))

这里我运行了上面的函数,但是指定了四种颜色进行绘图:

plotGantt(mydf1, res.col='group', start.col='startyear', end.col='endyear', 
          res.colors=c('red','orange','yellow','gray99'))

plotGantt(mydf2, res.col='group', start.col='startyear', end.col='endyear', 
          res.colors=c('red','orange','yellow','gray99'))

plotGantt(mydf3, res.col='group', start.col='startyear', end.col='endyear', 
          res.colors=c('red','orange','yellow','gray99'))

plotGantt(mydf4, res.col='group', start.col='startyear', end.col='endyear', 
          res.colors=c('red','orange','yellow','gray99'))

这些是地块:

我想做的是修改函数,以便:

1) 它将在 y 轴上绘制所有四个组,无论它们是否实际出现在数据中。

2) 无论有多少组,每个绘图的每个组都具有相同的颜色。如您所见,mydf2 有四个组,并且绘制了所有四种颜色(1-红色、2-橙色、3-黄色、4-灰色)。这些颜色实际上是使用与 mydf3 相同的组绘制的,因为它只包含组 2、3、4,并且颜色是按相反的顺序选择的。但是 mydf1 和 mydf4 为每个组绘制了不同的颜色,因为它们没有任何第 4 组。灰色仍然是第一个选择的颜色,但现在它用于最低出现的组(mydf1 中的 group2 和 mydf3 中的 group3)。

在我看来,我需要处理的主要事情是函数内部的向量“资源”,并且不仅包含唯一组,而且包含所有组。当我尝试手动覆盖以确保它包含所有组时,例如做一些像resources &lt;-as.factor(1:4) 这样简单的事情然后我得到一个错误:

'Error in rect(start, yBottom, end, yTop, col = color) : cannot mix zero-length and non-zero-    length coordinates' 

大概for循环不知道如何为不存在的组绘制不存在的数据。

我希望这是一个可复制/可读的问题,并且很清楚我想要做什么。

编辑:我意识到要解决颜色问题,我可以为每个示例 dfs 中存在的 3 个组指定颜色。但是,我的意图是将此图用作函数的输出,如果所有组都存在于特定 df,则不会提前知道它。

【问题讨论】:

  • “base R”中没有甘特图。最接近的是 gantt.chart 包 plotrix。
  • @BondedDust 你读过第一句话吗?
  • 我做到了。我提供了一个实现的参考。请求一个能够“知道”没有被传递给它的对象的函数似乎是荒谬的。
  • 我会修改这个问题,因为它不是最小的。现在你已经包含了太多的代码和信息,如果不花大量时间解析问题,就很难弄清楚你想要什么。

标签: r plot


【解决方案1】:

我稍微修改了您的函数以在开始和结束日期中考虑NA

plotGantt <- function(data, res.col='resources', 
                      start.col='start', end.col='end', res.colors=rainbow(30))
{
  #slightly enlarge Y axis margin to make space for labels
  op <- par('mar')
  par(mar = op + c(0,1.2,0,0)) 

  minval <- min(data[,start.col],na.rm=T)
  maxval <- max(data[,end.col],na.rm=T)

  res.colors <- rev(res.colors)
  resources <- sort(unique(data[,res.col]),decreasing=T)


  plot(c(minval,maxval),
       c(0.5,length(resources)+0.5),
       type='n', xlab='Duration',ylab=NA,yaxt='n' )
  axis(side=2,at=1:length(resources),labels=resources,las=1)
  for(i in 1:length(resources))
  {
    yTop <- i+0.5
    yBottom <- i-0.5
    subset <- data[data[,res.col] == resources[i],]
    for(r in 1:nrow(subset))
    {
      color <- res.colors[((i-1)%%length(res.colors))+1]
      start <- subset[r,start.col]
      end <- subset[r,end.col]
      rect(start,yBottom,end,yTop,col=color)
    }
  }
  par(mar=op) # reset the plotting margins
  invisible()
}

通过这种方式,如果您只是将所有可能的组值附加到您的数据中,您就会将它们打印在 y 轴上。例如:

mydf1 <- data.frame(startyear=2000:2009, endyear=2001:2010,
                    group=c(1,1,1,1,2,2,2,1,1,1))
# add all the group values you want to print with NA dates
mydf1 <- rbind(mydf1,data.frame(startyear=NA,endyear=NA,group=1:4))

plotGantt(mydf1, res.col='group', start.col='startyear', end.col='endyear', 
          res.colors=c('red','orange','yellow','gray99'))

关于颜色,目前已排序的res.colors 应用于已排序的组;所以res.colors 中的第一种颜色应用于第一个(排序)组,依此类推...

【讨论】:

  • 哇!这太好了-谢谢。使用 NA 很有意义。
猜你喜欢
  • 2012-05-16
  • 1970-01-01
  • 2020-09-01
  • 1970-01-01
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-01
相关资源
最近更新 更多