Chỉ định định dạng Ngày tùy chỉnh cho đối số colClasses trong read.table / read.csv


101

Câu hỏi:

Có cách nào để chỉ định định dạng Ngày khi sử dụng đối số colClasses trong read.table / read.csv không?

(Tôi nhận ra rằng tôi có thể chuyển đổi sau khi nhập, nhưng với nhiều cột ngày như thế này, sẽ dễ dàng hơn để thực hiện điều đó trong bước nhập)


Thí dụ:

Tôi có .csv với các cột ngày ở định dạng %d/%m/%Y.

dataImport <- read.csv("data.csv", colClasses = c("factor","factor","Date"))

Điều này làm cho chuyển đổi sai. Ví dụ, 15/07/2008trở thành 0015-07-20.


Mã có thể lặp lại:

data <- 
structure(list(func_loc = structure(c(1L, 2L, 3L, 3L, 3L, 3L, 
3L, 4L, 4L, 5L), .Label = c("3076WAG0003", "3076WAG0004", "3076WAG0007", 
"3076WAG0009", "3076WAG0010"), class = "factor"), order_type = structure(c(3L, 
3L, 1L, 1L, 1L, 1L, 2L, 2L, 3L, 1L), .Label = c("PM01", "PM02", 
"PM03"), class = "factor"), actual_finish = structure(c(4L, 6L, 
1L, 2L, 3L, 7L, 1L, 8L, 1L, 5L), .Label = c("", "11/03/2008", 
"14/08/2008", "15/07/2008", "17/03/2008", "19/01/2009", "22/09/2008", 
"6/09/2007"), class = "factor")), .Names = c("func_loc", "order_type", 
"actual_finish"), row.names = c(NA, 10L), class = "data.frame")


write.csv(data,"data.csv", row.names = F)                                                        

dataImport <- read.csv("data.csv")
str(dataImport)
dataImport

dataImport <- read.csv("data.csv", colClasses = c("factor","factor","Date"))
str(dataImport)
dataImport

Và đây là kết quả đầu ra:

đầu ra mã


Một cách hay ho để làm điều này là tạo phiên bản của riêng bạn read.tablevà thêm một formatđối số được chuyển đến as.Date. Tuy nhiên, tôi sẽ không ngạc nhiên nếu có một cách tốt hơn mà tôi chưa nghĩ ra.
joran

Câu trả lời:


158

Bạn có thể viết hàm của riêng mình chấp nhận một chuỗi và chuyển đổi nó thành Ngày bằng định dạng bạn muốn, sau đó sử dụng setAsđể đặt nó làm asphương thức. Sau đó, bạn có thể sử dụng chức năng của mình như một phần của colClasses.

Thử:

setAs("character","myDate", function(from) as.Date(from, format="%d/%m/%Y") )

tmp <- c("1, 15/08/2008", "2, 23/05/2010")
con <- textConnection(tmp)

tmp2 <- read.csv(con, colClasses=c('numeric','myDate'), header=FALSE)
str(tmp2)

Sau đó, sửa đổi nếu cần để làm việc cho dữ liệu của bạn.

Biên tập ---

Bạn có thể muốn chạy setClass('myDate')trước để tránh cảnh báo (bạn có thể bỏ qua cảnh báo, nhưng nó có thể gây phiền nhiễu nếu bạn làm điều này nhiều và đây là một lệnh gọi đơn giản để loại bỏ nó).


2
Wow - setAs là một cứu cánh! Làm thế nào tôi chưa bao giờ thấy chức năng này trước đây?
user295691 5/12/12

4
Lưu ý rằng bạn có thể nhận được cảnh báo 'không có định nghĩa cho lớp "myDate"' như được nêu chi tiết trong câu hỏi này .
Danny D'Amours

1
Phải setMethod('myDate')làm gì? Chạy nó chỉ mang lại cho tôi một lỗi ...
Josh O'Brien

1
@ JoshO'Brien, xin lỗi điều đó đáng lẽ đã được setClasssửa (đã sửa ngay bây giờ). Những gì nó làm là ngăn không cho setAsđưa ra cảnh báo về 'myDate' không tồn tại dưới dạng một lớp. Cảnh báo là vô hại và mọi thứ vẫn hoạt động, nhưng thiết lập lớp có nghĩa là bạn thậm chí không thấy cảnh báo.
Greg Snow,

1
@MySchizoBuddy, Nếu bạn chỉ có một cột ngày tháng và bạn đang thực hiện việc này một lần thì có lẽ bạn làm theo cách nào không quan trọng. Nhưng nếu bạn có một số cột trong tập dữ liệu là ngày tháng, thì tôi nghĩ cách tiếp cận này có lẽ sẽ đơn giản hơn là thay đổi từng cột sau khi đọc.
Greg Snow

25

Nếu chỉ có 1 định dạng ngày bạn muốn thay đổi, bạn có thể sử dụng Defaultsgói để thay đổi định dạng mặc định trongas.Date.character

library(Defaults)
setDefaults('as.Date.character', format = '%d/%M/%Y')
dataImport <- read.csv("data.csv", colClasses = c("factor","factor","Date"))
str(dataImport)
## 'data.frame':    10 obs. of  3 variables:
##  $ func_loc     : Factor w/ 5 levels "3076WAG0003",..: 1 2 3 3 3 3 3 4 4 5
##  $ order_type   : Factor w/ 3 levels "PM01","PM02",..: 3 3 1 1 1 1 2 2 3 1
##  $ actual_finish: Date, format: "2008-10-15" "2009-10-19" NA "2008-10-11" ...

Tôi nghĩ câu trả lời của @Greg Snow hay hơn nhiều, vì nó không thay đổi hành vi mặc định của một hàm thường được sử dụng.


7

Trong trường hợp bạn cần thời gian cũng có thể:

setClass('yyyymmdd-hhmmss')
setAs("character","yyyymmdd-hhmmss", function(from) as.POSIXct(from, format="%Y%m%d-%H%M%S"))
d <- read.table(colClasses="yyyymmdd-hhmmss", text="20150711-130153")
str(d)
## 'data.frame':    1 obs. of  1 variable:
## $ V1: POSIXct, format: "2015-07-11 13:01:53"

2

Một thời gian dài trước đây, vấn đề đã được giải quyết bởi Hadley Wickham. Vì vậy, ngày nay giải pháp được rút gọn thành oneliner:

library(readr)
data <- read_csv("data.csv", 
                  col_types = cols(actual_finish = col_datetime(format = "%d/%m/%Y")))

Có thể chúng ta muốn loại bỏ những thứ không cần thiết:

data <- as.data.frame(data)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.