shosaco / vistime

Pretty timelines in R.
https://shosaco.github.io/vistime
GNU General Public License v3.0
170 stars 11 forks source link

Add days after a date in the x-axis #15

Closed carlanetto closed 1 year ago

carlanetto commented 4 years ago

Hi! I need to create a timeline that shows the number of days after the start and not specific days in the x-axis. Is there a way of doing it? Thanks in advance Best regards

shosaco commented 4 years ago

I can't imagine what the result would look like, could you draw a picture or sketch?

carlanetto commented 4 years ago

It would look like any gantt chart, when you do not know yet when something will happen in time, just the order of events and number of days of each task:

https://images.app.goo.gl/SKx5D6EMuJedi4dP7

shosaco commented 4 years ago

The screenshot behind your link does show projects in the y-axis, not days, so kindly specify what you have tried and what is failing, thanks :)

carlanetto commented 4 years ago

The image says on the x-axis: “days of the month”. I wish to add numbers of days and not specific dates. Your package right now gives back an error and requested that the start and the end to be in a date format.

I want to add to the timeline: this project should start on day 6 and go until day 10 after the start of the project (that I don’t know when it will be). But without a month or year.

carlanetto commented 4 years ago

The image is of what I want to do and not an output of your package... Sorry, I thought that was clear

shosaco commented 4 years ago

So you are talking about the x-axis, not the y axis and already have tried something in code - please post this code as a starting point. The solution will be to convert your integer days into dates by using as.Date(2000-01-01) + your_days_vector.

carlanetto commented 4 years ago

I do not want it to show up like dates, so I don’t want to transform it do date. I just would like that the package does not require the input to be in a date format. This way the package could be applied in different contexts. But I will look for another solution in another package.

The code I am using is the example you give in the documentation.

Thanks for the attention

carlanetto commented 4 years ago

So you are talking about the x-axis, not the y axis and already have tried something in code - please post this code as a starting point. The solution will be to convert your integer days into dates by using as.Date(2000-01-01) + your_days_vector.

Thanks... indeed I am using it in x-axis, and I corrected it on the question. But it could actually be a nice idea to be able to flip the visualization.

shosaco commented 4 years ago

I used my suggestions and formatted the x-axis accordingly:

data <- read.csv(text="event,start,end
                       Phase 1,1,10
                       Phase 2,8,15", stringsAsFactors=FALSE)
data$start <- as.Date("2000-01-01") + data$start - 1
data$end <- as.Date("2000-01-01") + data$end - 1
gg_vistime(data) +
    scale_x_datetime(breaks = seq(min(as.POSIXct(data$start)), 
                                  max(as.POSIXct(data$end)), 
                                  "days"), 
                     date_labels = "%d") + 
    xlab("Day")

grafik

jonocarroll commented 1 year ago

This took me a while to figure out so here it is for anyone else searching...

The above solution works great for a static ggplot but doesn't work if you want to keep the plotly interactivity, which I did.

I re-worked the data example; in this case the start and end represent offsets from the start date. This is perhaps more common for 'days on study' or 'days since an significant event'

library(vistime)
## start and end represent days from 2000-01-01
## so starts are days 2 and 9, ends are days 11 and 16
data <- read.csv(text="event,start,end
                       Phase 1,1,10
                       Phase 2,8,15", stringsAsFactors=FALSE)
epoch <- as.POSIXct("2000-01-01", tz = "UTC")
data$start <- epoch + lubridate::days(data$start)
data$end <- epoch + lubridate::days(data$end)

Your example above still works (I shifted this to reflect 'days after start')

gg_vistime(data) +
  ggplot2::scale_x_datetime(breaks = seq(epoch, max(data$end), "days") - 1, 
                            date_labels = "%d") + 
  ggplot2::xlab("Day") 

gg_vistime

But by default, vistime() uses the dates

vistime(data)

vistime

The x-axis tick-labels can be specified in plotly using layout()

daysrange <- seq(epoch, to = max(data$end), "days")
ndays <- length(daysrange)

vistime(data) %>%
  plotly::layout(xaxis = list(title = "Offset Day", 
                              tickmode = "array",
                              tickvals = daysrange,
                              ticktext = 0:ndays))

vistime_offset

This also opens up the possibility of combining the two with custom labels

daystext <- paste0(0:ndays, "<br>(", format(daysrange, "%b %d"), ")")
daystext[1] <- sub(")", paste0(", ", lubridate::year(epoch), ")"), daystext[1])
vistime(data) %>%
  plotly::layout(xaxis = list(title = "Offset Day", 
                              tickmode = "array",
                              tickvals = daysrange[c(TRUE, FALSE)],
                              ticktext = daystext[c(TRUE, FALSE)]))

vistime_combined

Thanks for this package, it's very useful!