2015-11-12 13 views
7

Ho un frame di dati in cui data è memorizzato come double esempio, 1993.09 1993.10 1993.11 1993.12as.Date dal formato 'YYYY.mm'

voglio convertire questo in un formato data (con giorni sempre 1).

Per quanto ho capito, as.Date() vuole una stringa di input. Tuttavia, per qualche motivo quando converto le mie date nella stringa sapply(dates, as.character), gli zeri dopo quelli scompaiono, convertendo efficacemente da ottobre a gennaio, risultanti in due ganuari all'anno.

dates 
1993.07 1993.08 1993.09 1993.10 1993.11 1993.12 
sapply(dates, as.character) 
sub("[.]", " ", dates) 
"1993 07" "1993 08" "1993 09" "1993 1" "1993 11" "1993 12" 

C'è un modo più semplice per convertire le date? O dove rovino?

dput:

c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
1993.08, 1993.09, 1993.1, 1993.11, 1993.12) 

risposta

9

Il tuo problema è che avete qualcosa che è una stringa di caratteri, ma si presenta come un numerica e non avete preso cura di questo durante l'importazione. R non fa distinzione tra 1993.1 e 1993.10. Entrambi sono lo stesso numero. Pertanto, as.character(1993.10) restituisce "1993.1". È necessario utilizzare una funzione di formattazione per assicurarsi di ottenere due cifre dopo il periodo, perché a as.Date"1993.1" e "1993.01" sono lo stesso mese.

x <- c(1993.09, 1993.10, 1993.11, 1993.12) 
as.Date(sprintf("%.2f.01", x), format = "%Y.%m.%d") 
#[1] "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01" 

Naturalmente, x dovrebbe essere importati come personaggio per cominciare.

+0

Il '' dput' è x <- c (1.993,09, 1.993,1, 1.993,11, 1.993,12) ', ma le tue soluzioni funziona ancora. –

+0

@DavidArenburg R non si cura se gli dai '1993.1' o' 1993.10'. Questo è un doppio identico. – Roland

2

Usa paste0 per aggiungere il giorno in e la ricerca dei valori per la formattazione data da ?strptime. In caso di problemi con il doppio di formattazione delle stringhe, è possibile utilizzare formatC:

txtfield <- c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
    1993.08, 1993.09, 1993.1, 1993.11, 1993.12) 

as.Date(paste0(formatC(txtfield, digits=2, format="f"),".01"), "%Y.%m.%d") 

Spiegazione:

paste0 è una versione abbreviata di paste che non inserire spazi tra gli elementi incollati.
formatC, formatC, digits specifica il numero di cifre che si desidera dopo il segno decimale (nel nostro caso si desidera 2. il formato indica a R quale numero di formattazione utilizzare, nel nostro caso "f" restituisce i numeri numerici nel numero desiderato xxx.xxx formato
as.Date converte in un formato di data R nativo, con "% Y.% m.% d" che specifica l'anno intero (4 cifre) seguito da un punto, seguito dal mese numerico (2 cifre) seguito da un punto, . seguita da giorno numerica

risultati:

[1] "1993-01-01" "1993-02-01" "1993-03-01" "1993-04-01" "1993-05-01" "1993-06-01" 
[7] "1993-07-01" "1993-08-01" "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01" 
0

avrai bisogno di fare un po 'giocherellare con str Ings. Il modo più ovvio (per me *) sarebbe quello di "tamponare" il lato destro dei valori con zeri.

* che è una abbastanza grande avvertimento

dates <- c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
1993.08, 1993.09, 1993.10, 1993.11, 1993.12) 

library(magrittr) 
library(stringr) 
dates %<>% 
    str_pad(width = 7, side = "right", pad = "0") %>% 
    paste0(".01") %>% 
    as.Date(format = "%Y.%m.%d") 

dates 
6

Se si desidera semplicemente convertirlo in classe "Date" utilizzando il primo del mese, la soluzione di Roland sembra più diretta, ma ci sono alcune altre considerazioni come se si potrebbe voler utilizzare la fine del mese o se si davvero voglio rappresentare anno-mesi usando le date in primo luogo.

Il pacchetto zoo ha una classe "yearmon" che può rappresentare anni di mesi direttamente senza convertirli in date e ha anche il metodo as.Date.yearmon che ha un argomento frac= può essere utilizzato per indicare la frazione del modo attraverso il mese di convertirsi se vuoi la classe "Date".

Innanzitutto, assicurarsi che le date siano stringhe di caratteri. L'input nella domanda mostra 1993.10 come uno degli input, quindi dobbiamo assicurarci che ci sia uno zero finale. (Se gli input hanno già carattere con lo zero finale, questo non è un problema. Abbiamo assunto il caso peggiore in questo caso assumendo valori numerici, quindi è necessario convertirli esplicitamente in puntini di caratteri con uno 0 finale, se necessario.) Ora utilizzare as.yearmon con il formato "%Y.%m". Infine utilizzare as.Date.yearmon per convertire in classe "Date".

Forse il più grande vantaggio di questo approccio è che siamo riusciti a lasciare il risultato in "yearmon" classe (cioè omettere la parte "as.Date", ad esempio as.yearmon(sprintf("%.2f", dates)) o se le date sono state già stringhe di caratteri, dates.ch, con un finale 0 nel caso di "1993.10" poi basta as.yearmon(dates.ch, "%Y.%m"), che in realtà rappresentare ciò che avete di meglio da quando il giorno non è veramente significativo, dato che non era lì all'inizio. "yearmon" oggetti possono essere tracciati e risolto nel modo previsto.

Ecco la conversione Classe "Date" utilizzando "yearmon":

library(zoo) 

dates <- c(1993.07, 1993.08, 1993.09, 1993.1, 1993.11, 1993.12) # test input 


as.Date(as.yearmon(sprintf("%.2f", dates), "%Y.%m")) # 1st of month 
## [1] "1993-07-01" "1993-08-01" "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01" 

as.Date(as.yearmon(sprintf("%.2f", dates), "%Y.%m"), frac = 1) # last of month 
## [1] "1993-07-31" "1993-08-31" "1993-09-30" "1993-10-31" "1993-11-30" "1993-12-31" 

o se l'ingresso di test è simile al seguente:

dates.ch <- c("1993.07", "1993.08", "1993.09", "1993.10", "1993.11", "1993.12") # input 

as.Date(as.yearmon(dates.ch, "%Y.%m")) 

as.Date(as.yearmon(dates.ch, "%Y.%m"), frac = 1) 
+2

OK. Ho risolto. –

+0

Avere un upvote per l'ultima soluzione del mese. – Roland

+0

Avere un commento da parte mia per aver ricordato il pacchetto dello zoo, l'avevo dimenticato! –

Problemi correlati