2012-02-09 22 views
10

Bạn biết cách bạn có thể cung cấp một vectơ tên cho một khung dữ liệu để thay đổi tên col hoặc hàng của một khung dữ liệu. Có phương pháp tương tự nào để cung cấp một vectơ tên có làm thay đổi lớp của mỗi cột trong một khung dữ liệu không? Bạn có thể làm điều này khi bạn đọc trong một khung dữ liệu với read.table bằng cách sử dụng colClasses. Còn nếu dataframe được tạo bên trong R thì sao?cung cấp một véc tơ cho "các lớp" của khung dữ liệu

DF <- as.data.frame(matrix(rnorm(25), 5, 5)) 
str(DF) #all numeric modes 

names(DF) <- c("A", "A2", "B", "B2", "Z") #I want something like this for classes 
some_classes_function_like_names(DF) <- c(rep("character", 3), rep("factor", 2)) 

#I can do it like this but this seems inefficient 
DF[, 1:3] <- lapply(DF[, 1:3], as.character) 
DF[, 4:5] <- lapply(DF[, 4:5], as.factor) 

str(DF) 

CHỈNH SỬA: Tôi đã thay đổi một cách ngẫu nhiên ở trên để tỏ ra không hợp lý.

EDIT 2: Nếu có một cách để viết một người sử dụng được xác định chức năng đó sẽ đủ cũng

Trả lời

5

Dường class(x) <- "factor" không làm việc và cũng như thế as(x, "factor"), vì vậy tôi không biết một cách trực tiếp làm bạn muốn gì.

... Nhưng một cách rõ ràng hơn một chút là:

# Coerces data.frame columns to the specified classes 
colClasses <- function(d, colClasses) { 
    colClasses <- rep(colClasses, len=length(d)) 
    d[] <- lapply(seq_along(d), function(i) switch(colClasses[i], 
     numeric=as.numeric(d[[i]]), 
     character=as.character(d[[i]]), 
     Date=as.Date(d[[i]], origin='1970-01-01'), 
     POSIXct=as.POSIXct(d[[i]], origin='1970-01-01'), 
     factor=as.factor(d[[i]]), 
     as(d[[i]], colClasses[i]))) 
    d 
} 

# Example usage 
DF <- as.data.frame(matrix(rnorm(25), 5, 5)) 
DF2 <- colClasses(DF, c(rep("character", 3), rep("factor", 2))) 
str(DF2) 

DF3 <- colClasses(DF, 'Date') 
str(DF3) 

Một vài điều: bạn có thể thêm các trường hợp khi cần thiết. Và dòng đầu tiên của hàm cho phép bạn gọi bằng một tên lớp duy nhất. Trường hợp "mặc định" cuối cùng của số switch gọi hàm as và bạn có thể thay đổi số dặm.

+0

@ Tommy Tôi đã hy vọng cho câu trả lời "Bạn dope đã có một chức năng cơ sở mà không dễ dàng". Chức năng của bạn hoạt động tốt. Tôi sẽ ném nó vào. Của tôi() như là một chức năng thuận tiện cho bản thân mình. Tôi thực sự hơi ngạc nhiên khi nhóm R-core chưa thực hiện một cái gì đó như thế này đặc biệt vì nó có vẻ là một phần của read.table. Cảm ơn bạn. –

+0

@Tyler Tôi đã chia sẻ sự ngạc nhiên của bạn. Tôi đã từ lâu tìm kiếm một chức năng cơ bản để làm điều này, và thường có một số cách tiếp cận quảng cáo hoc trên bay. Sẽ rất tuyệt nếu đội R-core xem xét điều này ở cơ sở. – digitalmaps

8

Hãy thử điều này:

toCls <- function(x, cls) do.call(paste("as", cls, sep = "."), list(x)) 
replace(DF,, Map(toCls, DF, cls)) 

dụ thứ hai. Ngoài ra hãy thử ví dụ này (cho phép NA được sử dụng cho bất kỳ cột nào mà lớp đó không bị thay đổi). Chúng tôi tải gói sở thú vì nó cung cấp phiên bản as.Date có nguồn gốc mặc định và chúng tôi xác định as.POSIXct2 của riêng mình để tránh việc phải chỉ định nguồn gốc khác.

library(zoo) # supplies alternate as.Date with a default origin 
as.NA <- identity 
as.POSIXct2 <- function(x) as.POSIXct(x, origin = "1970-01-01") 

cls2 <- c("character", "Date", NA, "factor", "POSIXct2") 
replace(DF,, Map(toCls, DF, cls2)) 

Lưu ý rằng nó chỉ khi chuyển đổi số để "Date" hoặc "POSIXct" rằng có những cân nhắc nguồn gốc và khi chuyển đổi chuỗi ký tự như "2000-01-01" không nguồn gốc sẽ cần phải được quy định trong mọi trường hợp như vậy cho tình huống như vậy chúng ta sẽ không cần phải tải vườn thú và chúng tôi sẽ không cần phiên bản riêng của chúng tôi as.POSIXct.

EDIT: Đã thêm một ví dụ khác.

Các vấn đề liên quan