Gantt style time line plot (in base R)

后端 未结 3 1492
一向
一向 2020-12-01 06:10

I have a dataframe that looks like this:

       person n start end
1         sam 6     0   6
2        greg 5     6  11
3     teacher 4    11  15
4         sa         


        
相关标签:
3条回答
  • 2020-12-01 06:37

    Pretty similar to @John's approach, but since I did it, I will post it :)

    Here's a generic function to plot a gantt (no dependencies):

    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.1
        yBottom <- i-0.1
        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
    }
    

    Usage example:

    data <- read.table(text=
    '"person","n","start","end"
    "sam",6,0,6
    "greg",5,6,11
    "teacher",4,11,15
    "sam",4,15,19
    "greg",5,19,24
    "sally",5,24,29
    "greg",4,29,33
    "sam",3,33,36
    "sally",5,36,41
    "researcher",6,41,47
    "greg",6,47,53',sep=',',header=T)
    
    plotGantt(data, res.col='person',start.col='start',end.col='end',
              res.colors=c('green','blue','brown','red','yellow'))
    

    Result:

    enter image description here

    0 讨论(0)
  • 2020-12-01 06:38

    While the y-axis is categorical all you need to do is assign numbers to the categories (1:5) and track them. Using the default as.numeric() of the factor will usually number them alphabetically but you should check anyway. Make your plot with the xaxt = 'n' argument. Then use the axis() command to put in a y-axis.

    axis(2, 1:5, myLabels)
    

    Keep in mind that whenever you're plotting the only way to place things is with a number. Categorical x or y values are always just the numbers 1:nCategories with category name labels in place of the numbers on the axis.

    Something like the following gets you close enough (assuming your data.frame object is called datf)...

    datf$pNum <- as.numeric(datf$person)
    plot(datf$pNum, xlim = c(0, 53), type = 'n', yaxt = 'n', xlab ='Duration (words)', ylab = 'person', main = 'Speech Duration')
    axis(2, 1:5, sort(unique(datf$person)), las = 2, cex.axis = 0.75)
    with(datf, segments(start, pNum, end, pNum, lwd = 3, lend=2))
    
    0 讨论(0)
  • 2020-12-01 06:40

    You say you want a base R solution, but you don't say why. Since this is one line of code in ggplot, I show this anyway.

    library(ggplot2)
    ggplot(dat, aes(colour=person)) + 
        geom_segment(aes(x=start, xend=end, y=person, yend=person), size=3) +
        xlab("Duration")
    

    enter image description here

    0 讨论(0)
提交回复
热议问题