2012-01-19 18 views
12

Il mio obiettivo è creare un vettore di timestamp POSIXct dato un inizio, una fine e un delta (15 minuti, 1 ora, 1 giorno). Ho sperato che potrei usare seq per questo, ma ho un problema di conversione tra la rappresentazione numerica e POSIXct:seq() per POSIXct

now <- Sys.time() 
now 
# [1] "2012-01-19 10:30:39 CET" 
as.POSIXct(as.double(now), origin="1970-01-01", tz="CET") 
# [1] "2012-01-19 09:30:39 CET" 
as.POSIXct(as.double(now), origin=as.POSIXct("1970-01-01", tz="CET"), tz="CET") 
# [1] "2012-01-19 09:30:39 CET" 

Un'ora si perde durante questa conversione. Che cosa sto facendo di sbagliato?

risposta

20

C'è un metodo seq() per gli oggetti della classe "POSIXt" che è la classe eccellente delle classi "POSIXlt" e "POSIXct". In quanto tale non è necessario effettuare alcuna conversione.

> now <- Sys.time() 
> tseq <- seq(from = now, length.out = 100, by = "mins") 
> length(tseq) 
[1] 100 
> head(tseq) 
[1] "2012-01-19 10:52:38 GMT" "2012-01-19 10:53:38 GMT" 
[3] "2012-01-19 10:54:38 GMT" "2012-01-19 10:55:38 GMT" 
[5] "2012-01-19 10:56:38 GMT" "2012-01-19 10:57:38 GMT" 
+3

E questo è indicato nella documentazione di seq(), dove avrei dovuto cercare in primo luogo. Grazie! –

+0

vedi la risposta di RichieCotton qui sotto se ne hai bisogno a intervalli regolari come "10 min" – d8aninja

3

Non ho una risposta al tuo problema, ma ho un modo alternativo di creare vettori di oggetti POSIXct. Se, ad esempio, si desidera creare un vettore di 1000 timestamp da ora con un delta_t di 15 minuti:

now = Sys.time() 
dt = 15 * 60 # in seconds 
timestamps = now + seq(0, 1000) * dt 
> head(timestamps) 
[1] "2012-01-19 11:17:46 CET" "2012-01-19 11:32:46 CET" 
[3] "2012-01-19 11:47:46 CET" "2012-01-19 12:02:46 CET" 
[5] "2012-01-19 12:17:46 CET" "2012-01-19 12:32:46 CET" 

Il trucco è che si può aggiungere un vettore di secondi per un oggetto POSIXct.

7

Questi problemi relativi al fuso orario sono sempre complessi, ma il problema è che la tua origine viene calcolata nel fuso orario sbagliato (poiché la stringa specifica solo la data).

Provare a utilizzare origin <- now - as.numeric(now).

In alternativa, utilizzare lubridate::origin, che è la stringa "1970-01-01 UTC".


Una soluzione completa, sempre utilizzando lubridate.

start <- now() 
seq(start, start + days(3), by = "15 min") 
+0

Questo (origine <- now - as.numeric (now)) funziona, grazie! –

+0

Bisogna fare attenzione però, poiché funziona solo quando si esegue la conversione nelle impostazioni locali correnti. Una soluzione più generale è data nella mia risposta. L'idea è la stessa, ma è indipendente dal tuo locale. –

+1

@Richie Usando l'esempio 'lubridate', sto ricevendo' stringa non valida per "per" ' –

10

Bisogna essere consapevoli del fatto che durante la conversione da POSIXct a numerico, R prende il fuso orario in considerazione ma sempre inizia a contare da un'origine GMT:

> xgmt <- as.POSIXct('2011-01-01 14:00:00',tz='GMT') 
> xest <- as.POSIXct('2011-01-01 14:00:00',tz='EST') 
> (as.numeric(xgmt) - as.numeric(xest))/3600 
[1] -5 

Come si vede, il tempo in EST è concepito per essere cinque ore prima dell'orario in GMT, che è la differenza di tempo tra i due fusi orari. È quel valore che viene salvato internamente.

La funzione as.POSIXCT() aggiunge solo un attributo che contiene il fuso orario. Non altera il valore, quindi ottieni il tempo presentato in GMT, ma con un attributo che indica che è EST. Ciò significa anche che una volta passato da POSIXct a numerico, è necessario trattare i dati come se fosse ora GMT. (È molto più complesso di così, ma è l'idea generale). Quindi, si deve calcolare l'offset come segue:

> nest <- as.numeric(xest) 
> origin <- as.POSIXct('1970-01-01 00:00:00',tz='EST') 
> offset <- as.numeric(origin) 
> as.POSIXct(nest-offset,origin=origin) 
[1] "2011-01-01 14:00:00 EST" 

Questo funziona indipendentemente dal fuso orario è nel vostro locale (nel mio caso, che in realtà CET). Si noti inoltre che il comportamento dei dati del fuso orario può variare tra i sistemi.

4

Un'alternativa all'utilizzo seq.POSIXt è xts::timeBasedSeq, che permette di specificare la sequenza come una stringa:

library(xts) 
now <- Sys.time() 
timeBasedSeq(paste("2012-01-01/",format(now),"/H",sep="")) # Hourly steps 
timeBasedSeq(paste("2012-01-01/",format(now),"/d",sep="")) # Daily steps 
1

è necessario utilizzare seguenti (da = marcia, a = fine, da = passo).Tieni presente che al passaggio puoi utilizzare "giorni" o un numero intero che definisce quanti secondi trascorrono da un articolo all'altro.

+0

Hai bisogno di leggere le altre risposte prima di postarne una nuova 3 anni dopo. Questo è stato già fornito in almeno due risposte precedenti. –