2011-09-16 14 views
7

ho alcuni dati molto semplici in R che ha bisogno di avere il suo formato della data è cambiato:Cambiare formato della data in R

date midpoint 
1 31/08/2011 0.8378 
2 31/07/2011 0.8457 
3 30/06/2011 0.8147 
4 31/05/2011 0.7970 
5 30/04/2011 0.7877 
6 31/03/2011 0.7411 
7 28/02/2011 0.7624 
8 31/01/2011 0.7665 
9 31/12/2010 0.7500 
10 30/11/2010 0.7734 
11 31/10/2010 0.7511 
12 30/09/2010 0.7263 
13 31/08/2010 0.7158 
14 31/07/2010 0.7110 
15 30/06/2010 0.6921 
16 31/05/2010 0.7005 
17 30/04/2010 0.7113 
18 31/03/2010 0.7027 
19 28/02/2010 0.6973 
20 31/01/2010 0.7260 
21 31/12/2009 0.7154 
22 30/11/2009 0.7287 
23 31/10/2009 0.7375 

Piuttosto che %d/%m/%Y, vorrei che nel formato standard R di %Y-%m-%d

Come posso apportare questa modifica? Ho provato:

nzd$date <- format(as.Date(nzd$date), "%Y/%m/%d") 

Ma che appena tagliato l'anno e ha aggiunto zeri al giorno:

[1] "0031/08/20" "0031/07/20" "0030/06/20" "0031/05/20" "0030/04/20" 
[6] "0031/03/20" "0028/02/20" "0031/01/20" "0031/12/20" "0030/11/20" 
[11] "0031/10/20" "0030/09/20" "0031/08/20" "0031/07/20" "0030/06/20" 
[16] "0031/05/20" "0030/04/20" "0031/03/20" "0028/02/20" "0031/01/20" 
[21] "0031/12/20" "0030/11/20" "0031/10/20" "0030/09/20" "0031/08/20" 
[26] "0031/07/20" "0030/06/20" "0031/05/20" "0030/04/20" "0031/03/20" 
[31] "0028/02/20" "0031/01/20" "0031/12/20" "0030/11/20" "0031/10/20" 
[36] "0030/09/20" "0031/08/20" "0031/07/20" "0030/06/20" "0031/05/20" 

Grazie!

risposta

28

Ci sono due passaggi qui:

  • analizzare i dati. Il tuo esempio non è completamente riproducibile, sono i dati in un file o la variabile in una variabile di testo o fattore? Supponiamo quest'ultimo, poi se si data.frame si chiama X, si può fare
X$newdate <- strptime(as.character(X$date), "%d/%m/%Y") 

Ora la colonna newdate dovrebbe essere di tipo Date.

  • Formattare i dati. Questa è una questione di chiamare format() o strftime():
format(X$newdate, "%Y-%m-%d") 

Un esempio più completo:

R> nzd <- data.frame(date=c("31/08/2011", "31/07/2011", "30/06/2011"), 
+     mid=c(0.8378,0.8457,0.8147)) 
R> nzd 
     date mid 
1 31/08/2011 0.8378 
2 31/07/2011 0.8457 
3 30/06/2011 0.8147 
R> nzd$newdate <- strptime(as.character(nzd$date), "%d/%m/%Y") 
R> nzd$txtdate <- format(nzd$newdate, "%Y-%m-%d") 
R> nzd 
     date mid newdate txtdate 
1 31/08/2011 0.8378 2011-08-31 2011-08-31 
2 31/07/2011 0.8457 2011-07-31 2011-07-31 
3 30/06/2011 0.8147 2011-06-30 2011-06-30 
R> 

La differenza tra le colonne tre e quattro è il tipo: newdate è di classe Date mentre txtdate è un carattere.

+0

hmm, questo sembra estremamente complicato per un noob. Alla fine ho semplicemente cambiato la formattazione in Excel e ho letto il file CSV in R. Volevo sapere come cambiarlo facilmente in R, nel caso avessi un file molto più grande, ma non sembra così facile come dovrebbe essere. Non è un problema per la tua soluzione, speravo solo che fosse molto più semplice (forse un modo per convertire la colonna originale senza crearne una nuova). C'è un modo per cambiare prima la classe e poi formattarla? –

+1

@Yuri - Questo è essenzialmente ciò che la risposta di Dirk ti stava mostrando come fare, anche se ha creato alcune nuove colonne lungo la strada in modo da poter vedere facilmente cosa sta succedendo "sotto il cofano". Vi consiglio di seguire il suo esempio riga per riga, inserendo un 'str (x)' tra ogni riga in modo da poter vedere le differenze nell'azione. – Chase

+0

@Chase Grazie apprezzo la colonna in più per scopi pedagogici e mi ha aiutato a vedere la differenza di classe e il formato; quindi grazie per quello! Buono a sapersi, il passaggio extra con la colonna aggiuntiva non è strettamente necessario. Grazie a tutti e due! –

3

Dopo aver letto i dati in via di textConnection, il seguente sembra funzionare:

dat <- read.table(textConnection(txt), header = TRUE) 
dat$date <- strptime(dat$date, format= "%d/%m/%Y") 
format(dat$date, format="%Y-%m-%d") 

> format(dat$date, format="%Y-%m-%d") 
[1] "2011-08-31" "2011-07-31" "2011-06-30" "2011-05-31" "2011-04-30" "2011-03-31" 
[7] "2011-02-28" "2011-01-31" "2010-12-31" "2010-11-30" "2010-10-31" "2010-09-30" 
[13] "2010-08-31" "2010-07-31" "2010-06-30" "2010-05-31" "2010-04-30" "2010-03-31" 
[19] "2010-02-28" "2010-01-31" "2009-12-31" "2009-11-30" "2009-10-31" 

> str(dat) 
'data.frame': 23 obs. of 2 variables: 
$ date : POSIXlt, format: "2011-08-31" "2011-07-31" "2011-06-30" ... 
$ midpoint: num 0.838 0.846 0.815 0.797 0.788 ... 
+0

Questo cambia prima il tipo e poi lo formatta? –

+0

@Yuri - corretto. – Chase

+0

Ho una domanda su POSIXlt nei frame di dati come indicato qui: http://stackoverflow.com/questions/3355107/possibly-inconsistent-behavior-in-qplot Quando provo a tracciare la data come asse x in ggplot, ho ricevuto questo errore - Errore in if (lunghezza (intervallo) == 1 || diff (intervallo) == 0) {: valore mancante in cui TRUE/FALSE necessario - Come ottengo questo in POSIXct? –

0

credo che

nzd$date <- as.Date(nzd$date, format = "%d/%m/%Y") 

è sufficiente.

+0

Concordato, ma si basa su _magic_ (la formattazione predefinita), quindi è utile mostrare i passaggi distinti. –

+0

@Dirk In effetti, è per questo che ho votato per la tua risposta! ;) – joran

3

Si potrebbe anche usare la funzione parse_date_time dal pacchetto lubridate:

library(lubridate) 
day<-"31/08/2011" 
as.Date(parse_date_time(day,"dmy")) 
[1] "2011-08-31" 

parse_date_time restituisce un oggetto POSIXct, in modo da utilizzare as.Date per ottenere un oggetto data. Il primo argomento di parse_date_time specifica un vettore di data, il secondo argomento specifica l'ordine in cui si verifica il formato. L'argomento orders rende lo standard parse_date_time molto flessibile.

5
nzd$date <- format(as.Date(nzd$date), "%Y/%m/%d") 

Nel codice di cui sopra, ci sono due errori. Prima di tutto, quando stai leggendo nzd$date all'interno di as.Date non stai menzionando in che formato lo stai alimentando il date. Quindi, prova il suo formato predefinito per leggerlo. Se si vede il help doc, ?as.Date vedrete

formato
Una stringa di caratteri. Se non specificato, proverà "% Y-% m-% d" quindi "% Y /% m /% d" sul primo elemento non NA e darà un errore se nessuno dei due funziona. In caso contrario, il trattamento avviene tramite strptime

Il secondo errore è: anche se si desidera leggere in formato %Y-%m-%d, all'interno format hai scritto "%Y/%m/%d".

Ora, il modo corretto di farlo è:

> nzd <- data.frame(date=c("31/08/2011", "31/07/2011", "30/06/2011"), 
+          mid=c(0.8378,0.8457,0.8147)) 
> nzd 
     date mid 
1 31/08/2011 0.8378 
2 31/07/2011 0.8457 
3 30/06/2011 0.8147 
> nzd$date <- format(as.Date(nzd$date, format = "%d/%m/%Y"), "%Y-%m-%d") 
> head(nzd) 
     date mid 
1 2011-08-31 0.8378 
2 2011-07-31 0.8457 
3 2011-06-30 0.8147 
Problemi correlati