Search code examples
rdata-visualizationdata-manipulationtimelinevistime

Merging Timelines Together to Make One Timeline Using Vistime Package in R


When attempting to create a timeline via vistime an overlap in the dates produces a graphic more like a gantt chart which is undesirable. I wish to have one continous timeline.

Below I have shown the current issue and the desired result.

Current Output:

library(vistime)
syst2 <- data.frame(Position = c(0,0,rep(c( 1,0), 3)),
        Name = rep(c("SYS2", "SYS2","SYS4","SYS4"), each=2),
        start = c("2018-10-01","2018-10-11","2018-11-26","2018-12-06","2018-10-01","2018-10-24","2018-11-23","2018-12-05"),
        end = c("2018-10-16","2018-11-26","2018-12-06","2018-12-31","2018-10-24","2018-11-23","2018-12-05","2018-12-31"),
        color = c('#FF0000','#FF0000',rep(c("#008000",'#FF0000'), 3)),
        fontcolor = c('#FF0000','#FF0000',rep(c("#008000",'#FF0000'), 3)))


vistime(syst2, events = "Position", groups = "Name")

enter image description here

Desired Output: How can I merge date ranges of overlapping periods for similar positions (e.g. 0 or 1)?

syst2 <- data.frame(Position = c(rep(c( 0,1), 3),0),
        Name = c(rep(c("SYS2"), each=3),rep(c("SYS4"), each=4)),
        start = c("2018-10-01","2018-11-26","2018-12-06","2018-10-01","2018-10-24","2018-11-23","2018-12-05"),
        end = c("2018-11-26","2018-12-06","2018-12-31","2018-10-24","2018-11-23","2018-12-05","2018-12-31"),
        color = c(rep(c('#FF0000',"#008000"), 3),'#FF0000'),
        fontcolor = c(rep(c('#FF0000',"#008000"), 3),'#FF0000'))


vistime(syst2, events = "Position", groups = "Name")

enter image description here


Solution

  • This can be achieved in two ways:

    1.) Correcting the data before drawing it

    syst2 <- data.frame(Position = c(0,0,rep(c( 1,0), 3)),
                        Name = rep(c("SYS2", "SYS2","SYS4","SYS4"), each=2),
                        start = c("2018-10-01","2018-10-11","2018-11-26","2018-12-06","2018-10-01","2018-10-24","2018-11-23","2018-12-05"),
                        end = c("2018-10-16","2018-11-26","2018-12-06","2018-12-31","2018-10-24","2018-11-23","2018-12-05","2018-12-31"),
                        color = c('#FF0000','#FF0000',rep(c("#008000",'#FF0000'), 3)))
    
    # make Dates comparable
    syst2$start <- as.Date(as.character(syst2$start))
    syst2$end <- as.Date(as.character(syst2$end))
    
    # check if ranges of the same type overlap, extend first range if it does
    syst2 <- syst2[order(syst2$Name, syst2$start),]
    for(row in 1:(nrow(syst2) - 1)) if(syst2$Name[row] == syst2$Name[row+1] & syst2$end[row] > syst2$start[row+1]){
      syst2$end[row] <- syst2$end[row+1]
      syst2$start[row+1] <- syst2$start[row]
    }
    
    # kill the duplicates
    syst2 <- unique(syst2)
    
    # draw it
    vistime(syst2, events = "Position", groups = "Name")
    

    enter image description here

    2. Manipulating the resulting vistime object after generation

    # repeating your setup
    syst2 <- data.frame(Position = c(0,0,rep(c( 1,0), 3)),
                    Name = rep(c("SYS2", "SYS2","SYS4","SYS4"), each=2),
                    start = c("2018-10-01","2018-10-11","2018-11-26","2018-12-06","2018-10-01","2018-10-24","2018-11-23","2018-12-05"),
                    end = c("2018-10-16","2018-11-26","2018-12-06","2018-12-31","2018-10-24","2018-11-23","2018-12-05","2018-12-31"),
                    color = c('#FF0000','#FF0000',rep(c("#008000",'#FF0000'), 3)))
    
     p <- vistime(syst2, events = "Position", groups = "Name", showLabels = FALSE)
    
    # looping through all data, if any drawn data has y coordinates "2", change it to 1
    p$x$data <- lapply(p$x$data, function(l){
        if(all(l$y == 2)){
            l$y <- rep(1, length(l$y)) # lines have 2 y coordinates
            return(l)
        }else{
            return(l)
        }
    })
    
    p
    

    result after solution 2 I use vistime version 0.7.0.9000, which can be obtained by devtools::install_github("shosaco/vistime").

    Just one additional, independent, remark: It seems you don't want labels to be shown. You don't need to set the fontcolor column equal to color column for that. There is an extra argument for that purpose: showLabels = FALSE.