2012-02-09 14 views
10

Si sa come è possibile fornire un vettore di nomi a un frame di dati per modificare i nomi di colonna o di riga di un dataframe. Esiste un metodo simile per fornire un vettore di nomi che altera la classe di ogni colonna in un dataframe? Puoi farlo quando leggi in un dataframe con read.table usando colClasses. Che dire se il dataframe viene creato all'interno di R?fornisce un vettore a "classi" di dataframe

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) 

MODIFICA: Sono cambiato sontuosamente sopra in lapply perché non ha senso.

EDIT 2: Se c'è un modo per scrivere una funzione definita dall'utente che basterebbe così

risposta

5

Sembra class(x) <- "factor" non funziona e nemmeno as(x, "factor"), quindi non so di un modo diretto di fare ciò che vuoi.

... Ma un modo un po 'più esplicito è:

# 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) 

Un paio di cose: è possibile aggiungere più casi come necessario. E la prima riga della funzione ti consente di chiamare con un solo nome di classe. L'ultimo caso "predefinito" dello switch chiama la funzione as e il chilometraggio può variare.

+0

@ Tommy speravo nella risposta "La tua droga è già una funzione base che lo fa facilmente". Le tue funzioni funzionano bene. Inserirò il mio .First() come funzione di convenienza per me stesso. In realtà sono un po 'sorpreso dal fatto che il team R-core non abbia già implementato qualcosa di simile, specialmente perché sembra essere parte di read.table. Grazie. –

+0

@Tyler ho condiviso la tua sorpresa. Ho cercato a lungo una funzione di base per fare proprio questo, e di solito prendo qualche approccio ad hoc al volo. Sarebbe bello se il team R-core lo considerasse in base. – digitalmaps

8

Prova questo:

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

Secondo esempio. Prova anche questo esempio (che consente di utilizzare NA per qualsiasi colonna la cui classe non debba essere modificata). Carichiamo il pacchetto zoo poiché fornisce una versione di as.Date che ha un'origine predefinita e definiamo il nostro as.POSIXct2 allo stesso modo per evitare di dover specificare altrimenti l'origine.

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)) 

Nota che il suo solo quando la conversione dei numeri di "Date" o "POSIXct" che ci sono considerazioni di origine e per la conversione di stringhe di caratteri come "2000-01-01" dovrebbero essere specificate in ogni caso non provenienza, per tali situazioni non avremmo bisogno di caricare zoo e non avremmo bisogno della nostra versione di as.POSIXct.

MODIFICA: aggiunto un altro esempio.

Problemi correlati