2011-09-16 20 views
7

Mam kilka bardzo prostych danych w R, który musi mieć format daty zmiany:Zmiana formatu daty w 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 

Zamiast %d/%m/%Y chciałbym go w standardowym formacie R %Y-%m-%d

Jak mogę to zmienić? Próbowałem:

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

Ale to po prostu odciąć lat i dodaje zera do dnia:

[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" 

Dzięki!

Odpowiedz

28

Istnieją dwa kroki tutaj:

  • analizowania danych. Twój przykład nie jest w pełni odtwarzalny, czy dane w pliku, czy zmienna w zmiennej tekstowej lub czynnikowej? Załóżmy, ten ostatni, a następnie, jeśli data.frame nazywa się X, można zrobić
X$newdate <- strptime(as.character(X$date), "%d/%m/%Y") 

Teraz kolumna newdate powinny być typu Date.

  • Sformatuj dane. Że jest to kwestia nazywając format() lub strftime():
format(X$newdate, "%Y-%m-%d") 

Pełniejszy przykład:

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> 

Różnica między kolumnami trzy i cztery to typ: newdate jest z klasą Date, natomiast txtdate jest postacią.

+0

hmm, to wydaje się niezwykle skomplikowane dla noob. W końcu zmieniłem formatowanie w programie Excel i ponownie wczytałem plik CSV do R. Chciałem wiedzieć, jak łatwo zmienić go w R, w przypadku gdybym miał znacznie większy plik, ale to nie wydaje się prawie tak łatwe, jak to powinno być. Nie ma w tym nic złego, miałem tylko nadzieję, że jest o wiele prostsze (prawdopodobnie sposób na konwersję oryginalnej kolumny bez tworzenia nowej). Czy istnieje sposób, aby najpierw zmienić klasę, a następnie sformatować ją? –

+1

@Yuri - Zasadniczo odpowiedź Dirka pokazała ci, jak to zrobić, chociaż po drodze tworzył nowe kolumny, dzięki czemu możesz łatwo zobaczyć, co się dzieje "pod maską". Polecam przejść przez jego przykład linię po linii, wstawiając 'str (x)' pomiędzy liniami, aby zobaczyć różnice w działaniu. – Chase

+0

@Chase Dziękuję Doceniam dodatkową kolumnę do celów pedagogicznych i pomogło mi zobaczyć różnicę w klasie, a także format; dzięki za to! Dobrze wiedzieć, że dodatkowy krok z dodatkową kolumną nie jest absolutnie niezbędny. Dzięki wam oboje! –

3

Po przeczytaniu swoje dane poprzez textConnection dodaje wydaje się działać:

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

Czy to zmienia najpierw typ, a następnie go formatuje? –

+0

@ Yuri - poprawne. – Chase

+0

Mam pytanie dotyczące POSIXlt w ramkach danych, jak podano tutaj: http://stackoverflow.com/questions/3355107/possibly-inconsistent-behavior-in-qplot Kiedy próbuję wykreślić datę jako oś x w ggplot, otrzymuję ten błąd - Błąd w: if (długość (zakres) == 1 || diff (zakres) == 0) {: brakująca wartość, gdy potrzebne jest PRAWDA/FAŁSZ - Jak otrzymam to w POSIXct? –

0

wierzę, że

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

jest wystarczająca.

+0

Uzgodniono, ale opiera się on na _magic_ (domyślnym formatowaniu), więc dobrze jest pokazać różne kroki. –

+0

@Dirk Rzeczywiście, dlatego głosowałem za twoją odpowiedzią! ;) – joran

3

Można również użyć funkcji parse_date_time z pakietu lubridate:

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

parse_date_time zwraca obiekt POSIXct, więc używamy as.Date aby uzyskać obiekt daty. Pierwszy argument parse_date_time określa wektor daty, drugi argument określa kolejność, w jakiej występuje format. Argument orders jest bardzo elastyczny.

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

W powyższym kodzie występują dwa błędy. Przede wszystkim, gdy czytasz nzd$date wewnątrz as.Date, nie wspominasz w jakim formacie karmisz go date. Próbuje więc odczytać domyślny format zestawu. Jeśli widzisz help doc, ?as.Date widać

formatu
ciąg znaków. Jeśli nie zostanie określony, spróbuje "% Y-% m-% d" , a następnie "% Y /% m /% d" na pierwszym nie-NA elemencie, i da błąd , jeśli nie działa. W przeciwnym razie, przetwarzanie jest poprzez strptime

Drugim błędem jest: choć chciałbyś przeczytać w formacie %Y-%m-%d, wewnątrz format napisałeś "%Y/%m/%d".

Teraz jest poprawny sposób to zrobić jest:

> 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