2011-09-16 33 views
7

Tôi có một số dữ liệu rất đơn giản trong R mà cần phải có định dạng ngày của nó đã thay đổi:Thay đổi định dạng ngày tháng trong 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 

Thay vì %d/%m/%Y, tôi muốn nó theo định dạng R tiêu chuẩn của %Y-%m-%d

Tôi có thể thực hiện thay đổi này bằng cách nào? Tôi đã thử:

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

Nhưng đó chỉ là cắt đứt năm và thêm số không vào trong ngày:

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

Cảm ơn!

Trả lời

28

Có hai bước ở đây:

  • Phân tích các dữ liệu. Ví dụ của bạn không hoàn toàn có thể tái sản xuất, là dữ liệu trong một tệp hoặc biến trong một biến văn bản hoặc yếu tố? Giả sử sau này, sau đó nếu bạn data.frame được gọi là X, bạn có thể làm
X$newdate <- strptime(as.character(X$date), "%d/%m/%Y") 

Bây giờ cột newdate nên loại Date.

  • Định dạng dữ liệu. Đó là một vấn đề gọi format() hoặc strftime():
format(X$newdate, "%Y-%m-%d") 

Một ví dụ hoàn chỉnh hơn:

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> 

Sự khác biệt giữa các cột ba và bốn là loại: newdate là của lớp Date trong khi txtdate là ký tự.

+0

hmm, điều này dường như vô cùng phức tạp đối với một Noob. Tôi đã chỉ thay đổi định dạng trong excel và đọc file csv trở lại R. Tôi muốn biết làm thế nào để dễ dàng thay đổi nó trong R trong trường hợp tôi đã có một tập tin lớn hơn nhiều, nhưng điều này dường như không dễ dàng như nó nên là. Đó là không có chút ít về giải pháp của bạn, tôi đã chỉ hy vọng nó đã được đơn giản hơn nhiều (có thể là một cách để chuyển đổi cột ban đầu mà không cần tạo một cái mới). Có cách nào để thay đổi lớp học đầu tiên và sau đó định dạng nó? –

+1

@Yuri - Đó là bản chất câu trả lời của Dirk đã chỉ cho bạn cách làm, mặc dù anh ấy đã tạo ra một số cột mới dọc theo đường để bạn có thể dễ dàng nhìn thấy những gì đang xảy ra "dưới mui xe". Tôi khuyên bạn nên đi qua dòng ví dụ của mình bằng dòng, chèn một 'str (x)' ở giữa mỗi dòng để bạn có thể thấy sự khác biệt trong hành động. – Chase

+0

@Chase Cảm ơn tôi đã đánh giá cao cột phụ cho mục đích sư phạm và nó đã giúp tôi thấy sự khác biệt của lớp cũng như định dạng; cảm ơn vì điều đó! Điều cần biết là bước bổ sung với cột bổ sung là không cần thiết. Cảm ơn cả hai! –

3

Sau khi đọc dữ liệu của bạn trong qua một textConnection, sau đây dường như làm việc:

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

Điều này có thay đổi loại đầu tiên và sau đó định dạng không? –

+0

@Yuri - đúng. – Chase

+0

Tôi có câu hỏi về POSIXlt trong các khung dữ liệu như được tham chiếu tại đây: http://stackoverflow.com/questions/3355107/possibly-inconsistent-behavior-in-qplot Khi tôi cố vẽ đồ thị ngày dưới dạng trục x trong ggplot, tôi nhận được lỗi này - Lỗi trong if (length (range) == 1 || diff (range) == 0) {: thiếu giá trị trong đó TRUE/FALSE cần - Làm cách nào tôi nhận được điều này trong POSIXct? –

0

Tôi tin rằng

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

là đủ.

+0

Đồng ý, nhưng nó dựa trên _magic_ (định dạng mặc định) để có thể hiển thị các bước riêng biệt. –

+0

@Dirk Thật vậy, đó là lý do tôi bỏ phiếu cho câu trả lời của bạn! ;) – joran

3

Bạn cũng có thể sử dụng chức năng parse_date_time từ gói lubridate:

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

parse_date_time trả về một đối tượng POSIXct, vì vậy chúng tôi sử dụng as.Date để có được một đối tượng ngày. Đối số đầu tiên của parse_date_time chỉ định một vector ngày, đối số thứ hai chỉ định thứ tự mà định dạng của bạn xảy ra. Đối số orders làm cho parse_date_time rất linh hoạt.

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

Trong đoạn mã trên, có hai lỗi. Trước hết, khi bạn đang đọc nzd$date bên trong as.Date bạn không đề cập đến định dạng bạn đang cho nó date. Vì vậy, nó sẽ cố định định dạng thiết lập mặc định của nó để đọc nó. Nếu bạn thấy help doc, ?as.Date bạn sẽ thấy

định dạng
Một chuỗi ký tự. Nếu không được chỉ định, nó sẽ thử "% Y-% m-% d" rồi "% Y /% m /% d" trên phần tử phi NA đầu tiên và đưa ra lỗi nếu không hoạt động. Nếu không, quá trình xử lý là thông qua strptime

Sai lầm thứ hai là: ngay cả khi bạn muốn đọc nó ở định dạng %Y-%m-%d, bên format bạn đã viết "%Y/%m/%d".

Bây giờ, đúng cách để làm việc đó là:

> 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