2017-09-20 1 views
1

J'ai un ensemble de données qui a plusieurs collectes par jour certains jours. Je veux créer un champ que je peux utiliser pour regrouper les «jours», mais je veux me séparer à midi au lieu de minuit. Malheureusement, quand je fais le "split de midi", la valeur de la date passe par un nombre entier au lieu d'une valeur de date.Date de groupe à midi au lieu de minuit

Quelques exemples de code:

library(tidyverse) 
x <- as.POSIXct(Sys.time()) 

y <- as.tibble(x) 

#midnights comes through correctly as a date 
y %>% 
    mutate(midnights=as.Date(value)) 

#middays comes through as an integer instead of a date 
y %>% 
    mutate(middays=ifelse(as.numeric(format(value,"%H")) >= 12, 
         as.Date(value), 
         as.Date(value)-1)) 

Que dois-je faire différemment?

+1

Je ne sais pas ce que vous pourriez faire pour réparer votre code - mais qu'arrive-t Si vous ajoutez/soustrayez 12 heures à vos jours avant de les grouper, supprimez/ajoutez les 12 heures avant de les utiliser? – theGleep

Répondre

2

ifelse renvoie un caractère numérique car il supprime les informations de classe. Juste envelopper le tout dans un autre as.Date():

y %>% 
    mutate(middays=as.Date(ifelse(as.numeric(format(value,"%H")) >= 12, 
         as.Date(value), 
         as.Date(value)-1),origin="1970-01-01")) 

ou utiliser le if_else dans dplyr qui trie ceci

y %>% 
    mutate(middays=if_else(as.numeric(format(value,"%H")) >= 12, 
         as.Date(value), 
         as.Date(value)-1)) 

## A tibble: 1 × 2 
#    value middays 
#    <dttm>  <date> 
#1 2017-09-21 08:28:05 2017-09-19 
+0

if_else semble la solution la plus simple parmi les options :) – Margaret

2

Une astuce que vous pouvez utiliser est de convertir x à secondes depuis l'époque, en appelant as.numeric(x). Ensuite, pour obtenir le nombre de jours depuis l'époque, il est juste as.numeric(x) %/% 86400 (puisqu'il y a 86400 secondes dans une journée). Ainsi, vous pouvez utiliser cette valeur pour diviser par jour (c'est-à-dire séparer à minuit). Si vous voulez 'décaler' ceci de 12 heures, tout ce que vous devez faire est de déplacer x de 12 heures, c'est-à-dire de lancer as.numeric(dates + 12 * 3600) %/% 86400.

Par exemple

dates <- structure(c(1505771227.18457, 1505814427.18457, 1505857627.18457, 
     1505900827.18457, 1505944027.18457, 1505987227.18457, 
     1506030427.18457), class = c("POSIXct", "POSIXt")) 
#[1] "2017-09-18 22:47:07 BST" "2017-09-19 10:47:07 BST" "2017-09-19 22:47:07 BST" "2017-09-20 10:47:07 BST" 
#[5] "2017-09-20 22:47:07 BST" "2017-09-21 10:47:07 BST" "2017-09-21 22:47:07 BST" 

as.numeric(dates) %/% 86400 # use this to group by day (split at midnight) 
#[1] 17427 17428 17428 17429 17429 17430 17430 

as.numeric(dates + 12 * 3600) %/% 86400 # use this to split at noon 
#[1] 17428 17428 17429 17429 17430 17430 17431 

Alternativement, si vous souhaitez utiliser lubridate vous pouvez jouer le même tour, à savoir calculer lubridate::floor_date(dates + lubridate::hours(12), 'day') qui décale la date de 12 heures et trouve alors le jour, et le groupe par là.