ggplot2 not resizing plot for datetime vline

Viewed 112

When I add geom_hline()'s to a plot, the plot is resized to accommodate them. But when I add geom_vline()'s, the plot is not resized.

Why is this happening? How can I get the plot to resize?

MWE

library(ggplot2)

data <- data.frame(
  time=c(
    "2016-12-09T05:07:11Z", "2016-12-10T09:42:45Z", "2016-12-09T10:04:57Z",
    "2016-12-09T02:19:04Z", "2016-12-11T17:43:02Z", "2016-12-11T05:40:48Z",
    "2016-12-11T08:47:13Z", "2016-12-12T15:41:13Z"),
  value=c(23.3, 8.1, 12.9, 12.7, 5.6, 3.9, 5.5, 27.8)
)
# Each contains 3 values: 1 within the domain/range of `data` and 2 on either side
vlines <- data.frame(time=c("2016-12-07T00:00:00Z", "2016-12-11T00:00:00Z", "2016-12-14T00:00:00Z"))
hlines <- data.frame(value=c(-20, 10, 50))

data$time <- strptime(as.character(data$time), "%Y-%m-%dT%H:%M:%S", tz="UTC")
vlines$time <- strptime(as.character(vlines$time), "%Y-%m-%dT%H:%M:%S", tz="UTC")
vlines$timeNum <- as.numeric(vlines$time)

p <- ggplot(data, aes(x=time, y=value)) + geom_line()

ggsave("mwe1.pdf", p)

p <- p +
  geom_hline(data=hlines, aes(yintercept=value), color="red") +
  geom_vline(data=vlines, aes(xintercept=timeNum), color="blue")

ggsave("mwe2.pdf", p)

mwe1.pdf

Plot with data only

mwe2.pdf

Plot resized for <code>hlines</code>, but not <code>vlines</code>

Edit: sessionInfo()

R version 3.3.3 (2017-03-06)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: macOS Sierra 10.12.6

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  base     

other attached packages:
[1] ggplot2_2.2.1

loaded via a namespace (and not attached):
 [1] labeling_0.3     colorspace_1.3-2 scales_0.4.1     lazyeval_0.2.0  
 [5] plyr_1.8.4       tools_3.3.3      gtable_0.2.0     tibble_1.3.3    
 [9] Rcpp_0.12.12     grid_3.3.3       methods_3.3.3    rlang_0.1.1     
[13] munsell_0.4.3 
2 Answers

You can adjust x-axis using scale_x_date. Add limits to it with as.Date(range(vlines$time)).
Here is my code (adjusted according yours):

######################
# Generate input data   

data <- data.frame(
    time = c("2016-12-09T05:07:11Z", "2016-12-10T09:42:45Z", "2016-12-09T10:04:57Z",
             "2016-12-09T02:19:04Z", "2016-12-11T17:43:02Z", "2016-12-11T05:40:48Z",
             "2016-12-11T08:47:13Z", "2016-12-12T15:41:13Z"),
    value = c(23.3, 8.1, 12.9, 12.7, 5.6, 3.9, 5.5, 27.8))
data$time <- strptime(as.character(data$time), "%Y-%m-%dT%H:%M:%S", tz = "UTC")
data$time <- as.Date(data$time, "%Y-%m-%dT%H:%M:%S")

vlines <- data.frame(time = c("2016-12-07T00:00:00Z", 
                              "2016-12-11T00:00:00Z", 
                              "2016-12-14T00:00:00Z"))
vlines$time <- strptime(as.character(vlines$time), "%Y-%m-%dT%H:%M:%S", tz = "UTC")
vlines$timeNum <- as.Date(vlines$time, "%Y-%m-%dT%H:%M:%S")

hlines <- data.frame(value = c(-20, 10, 50))

######################
# Plot your timeseries   

library(ggplot2)
ggplot(data, aes(time, value)) + 
    geom_line() +
    geom_hline(data = hlines, aes(yintercept = value), color = "red") +
    geom_vline(data = vlines, aes(xintercept = timeNum), color = "blue") +
    scale_x_date(limits = as.Date(range(vlines$time)))

Result:

enter image description here

PS: I had to tweak some time/date conversions in you code to work (code that you provided didn't work for me).

Used sessionInfo():

R version 3.4.1 (2017-06-30)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Sierra 10.12.6

Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] ggplot2_2.2.1.9000 prompt_1.0.0       colorout_1.1-2    

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.12      memuse_3.0-1      clisymbols_1.2.0  crayon_1.3.2     
 [5] grid_3.4.1        plyr_1.8.4        gtable_0.2.0      scales_0.5.0.9000
 [9] rlang_0.1.2       lazyeval_0.2.0    labeling_0.3      munsell_0.4.3    
[13] compiler_3.4.1    colorspace_1.3-2  tibble_1.3.4   

@PoGibas's answer didn't quite work for me, but a slight modification of his approach did.

library(ggplot2)

data <- data.frame(
  time=c(
    "2016-12-09T05:07:11Z", "2016-12-10T09:42:45Z", "2016-12-09T10:04:57Z",
    "2016-12-09T02:19:04Z", "2016-12-11T17:43:02Z", "2016-12-11T05:40:48Z",
    "2016-12-11T08:47:13Z", "2016-12-12T15:41:13Z"),
  value=c(23.3, 8.1, 12.9, 12.7, 5.6, 3.9, 5.5, 27.8)
)
# Each contains 3 values: 1 within the domain/range of `data` and 2 on either side
vlines <- data.frame(time=c("2016-12-07T00:00:00Z", "2016-12-11T00:00:00Z", "2016-12-14T00:00:00Z"))
hlines <- data.frame(value=c(-20, 10, 50))

data$time <- strptime(as.character(data$time), "%Y-%m-%dT%H:%M:%S", tz="UTC")
vlines$time <- strptime(as.character(vlines$time), "%Y-%m-%dT%H:%M:%S", tz="UTC")
vlines$timeNum <- as.numeric(vlines$time)

p <- ggplot(data, aes(x=time, y=value)) +
  geom_line() +
  geom_hline(data=hlines, aes(yintercept=value), color="red") +
  geom_vline(data=vlines, aes(xintercept=timeNum), color="blue") +
  scale_x_datetime(limits=as.POSIXct(range(vlines$time))) # add datetime limits

ggsave("mwe3.pdf", p)

MWE3

Working example

I'm leaving this question as unanswered for now because I still don't understand why this is necessary. With this approach, if I have to add several pieces to a plot, I have to maintain xmin/xmax as I go to ensure everything is visible. As this isn't necessary with the geom_hline()'s, I still think I'm missing something vital.

Edit: I'm accepting @PoGibas' answer. Seems like this is just how ggplot2 is right now.

Related