1

For a journal, I was requested to transform my 24-hour x-axis into a 12-hour format with AM/PM format. I am using R with ggplot2 package to create my plots. For this, I did use the %p option allowing to see AM/PM. When I used it, it did not work at all. After looking on internet and discussing with colleagues, I realized that %p was not working on my Linux machine, but was working on my Mac machine. Thus, I would highly appreciate any feedback why.

Here is a reprex:

library(tidyverse)
library(lubridate)
library(ggplot2)

df <- tibble::tibble(ID = sample(seq(1, 3, 1), 289, replace = T), 
                     time = seq(as.POSIXct("2017-01-01", tz = "UTC"),
                                as.POSIXct("2017-01-02", tz = "UTC"),
                                by = "5 min"), 
                     date = lubridate::as_date(time),
                     outcome = sample(seq(70, 120, 1), 289, replace = T))


ggplot(df, aes(x = time, 
               y = outcome, 
               group = ID)) +
  geom_line(aes(color = factor(ID))) + 
  scale_y_continuous(limits = c(0, 150)) +
  scale_x_datetime(date_labels = ("%I %p"),
                   timezone = "GMT", 
                   date_breaks = "4 hours",
                   expand = c(0, 0))

The output on the Mac machine is:

enter image description here

The output on the Linux machine is:

enter image description here

Finally, the sessionInfo() for both:

  1. Mac:
sessionInfo(package = NULL) 
# R version 3.5.3 (2019-03-11) 
# Platform: x86_64-apple-darwin15.6.0 (64-bit) 
# Running under: macOS High Sierra 10.13.6 
# 
# Matrix products: default BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
# LAPACK: /Library/Frameworks/R.framework/Versions/3.5/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_3.2.1   lubridate_1.7.4 
#     
# loaded via a namespace (and not attached): 
#  [1] Rcpp_1.0.3       rstudioapi_0.10  magrittr_1.5     tidyselect_0.2.5 munsell_0.5.0    colorspace_1.4-1 R6_2.4.1         rlang_0.4.2      stringr_1.4.0    
# [10] dplyr_0.8.1      tools_3.5.3      grid_3.5.3       gtable_0.3.0     withr_2.1.2      digest_0.6.23    lazyeval_0.2.2   assertthat_0.2.1 tibble_2.1.3    
# [19] lifecycle_0.1.0  crayon_1.3.4     purrr_0.3.2      farver_2.0.1     glue_1.3.1       labeling_0.3     stringi_1.4.3    compiler_3.5.3   pillar_1.4.2    
# [28] scales_1.1.0     pkgconfig_2.0.3
  1. Linux:
sessionInfo(package = NULL)
# R version 3.6.2 (2019-12-12)
# Platform: x86_64-pc-linux-gnu (64-bit)
# Running under: Ubuntu 18.04.4 LTS
# 
# Matrix products: default
# BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
# LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1
# 
# Random number generation:
#  RNG:     Mersenne-Twister 
#  Normal:  Inversion 
#  Sample:  Rounding 
#  
# locale:
#  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=de_CH.UTF-8       
#  [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=de_CH.UTF-8    LC_MESSAGES=en_US.UTF-8   
#  [7] LC_PAPER=de_CH.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
# [10] LC_TELEPHONE=C             LC_MEASUREMENT=de_CH.UTF-8 LC_IDENTIFICATION=C       
# 
# attached base packages:
# [1] stats     graphics  grDevices utils     datasets  methods   base     
# 
# other attached packages:
# [1] ggplot2_3.2.1   lubridate_1.7.4
# 
# loaded via a namespace (and not attached):
#  [1] Rcpp_1.0.3       rstudioapi_0.10  magrittr_1.5     tidyselect_0.2.5 munsell_0.5.0   
#  [6] colorspace_1.4-1 R6_2.4.1         rlang_0.4.4      stringr_1.4.0    dplyr_0.8.3     
# [11] tools_3.6.2      grid_3.6.2       gtable_0.3.0     withr_2.1.2      digest_0.6.23   
# [16] lazyeval_0.2.2   assertthat_0.2.1 tibble_2.1.3     lifecycle_0.1.0  crayon_1.3.4    
# [21] purrr_0.3.3      farver_2.0.2     glue_1.3.1       labeling_0.3     stringi_1.4.5   
# [26] compiler_3.6.2   pillar_1.4.3     scales_1.1.0     pkgconfig_2.0.3

Thank you in advance for any guidance!

r2evans
  • 141,215
  • 6
  • 77
  • 149
Robin.N.
  • 99
  • 8
  • Please do not post an image of code/data/errors: it cannot be copied or searched (SEO), it breaks screen-readers, and it may not fit well on some mobile devices. Ref: https://meta.stackoverflow.com/a/285557/3358272 (and https://xkcd.com/2116/). Please just include the code or data (e.g., `dput(head(x))` or `data.frame(...)`) directly. – r2evans Feb 21 '20 at 06:56
  • I cannot reproduce the error. Running linux, the code returns the same as in your Mac example (correctly plotting with hh am/pm). I have the same versions of lubridate and ggplot2 installed. – MKR Feb 21 '20 at 07:06
  • @r2evans My code was put as code into my question. The pictures are only the output of the code and the output of the sessionInfo(). May I ask what is not correct in how ask my question in order to improve for the next time? Thank you – Robin.N. Feb 21 '20 at 07:17
  • @MKR thank you for the reply. Then, should I provide other information about my Linux machine? – Robin.N. Feb 21 '20 at 07:17
  • You provided code (my comment is cookie-cutter, I should have edited it, sorry), yes, and the images of the plots are fine. But why go through the trouble of doing screenshots of the console that lists your session info? It seems (to me) to be *at worst* the same amount of mouse/keyboard actions to paste an image and paste the code, so why make it unnecessarily graphical? I know it's easy, but ... for the reasons in my first comment, text is better whenever text is possible. – r2evans Feb 21 '20 at 07:19
  • 1
    @r2evans Oh, I see! Yes, I made a screenshot of the sessionInfo() because the copy/paste of the text made the output less readable. Thus, I made the decision to make a screenshot. I will correct it asap. Thank you – Robin.N. Feb 21 '20 at 07:24
  • 1
    I understand ... often (though it does not appear to be the case here), the perception of bad formatting is because the OP does not know how to format the question well, including code-blocks. Since you did that up-front, I'm not sure what would have been less readable, but I'm likely already biased against images of code :-). Thanks! – r2evans Feb 21 '20 at 07:32
  • Possibly it is due to your language settings on linux. – Esben Eickhardt Feb 21 '20 at 08:12
  • 1
    My guess would be this is a locale issue, but the locale in your session info looks normal. Could you test if you get different results using `stringi`, which has a more robust way of dealing with locales: `format(df$time, "%I %p")` vs `stringi::stri_datetime_format(df$time, "h a", locale = "en_US")`. (I'm on Ubuntu Linux and can't reproduce the problem btw.) – JBGruber Feb 21 '20 at 08:32
  • @JBGruber Your code ```stringi::stri_datetime_format(df$time, "h a", locale = "en_US")``` is working! I can see am/pm now! So, what should I change in my locale language setting? I would like to use my doe normally also... – Robin.N. Feb 21 '20 at 09:19

1 Answers1

2

Your problem appears to be the following setting: LC_TIME=de_CH.UTF-8. I assume the swiss German time format does not know AM/PM (because German doesn't use that nonese but proper 24h times). I see that you have locales availbe that can deal with that though. So you have to set one of the others for time locale:

Sys.setlocale("LC_TIME", "en_US.UTF-8")  

Test with:

format.Date(df$time, "%I %p")

And then see if the rest of your code works now. You have to set the locale after every restart of R or make the switch permanent using your R profile.

JBGruber
  • 11,727
  • 1
  • 23
  • 45