Снабдить вектор "классами" кадра данных

Вы знаете, как вы можете предоставить вектор имен для фрейма данных, чтобы изменить имена столбцов или строк в кадре данных. Есть ли аналогичный метод для подачи вектора имен, который изменяет класс каждого столбца в фрейме данных? Это можно сделать, когда вы читаете в dataframe с помощью read.table с помощью colClasses. Как насчет того, создается ли фреймворк внутри R?

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)

РЕДАКТИРОВАТЬ: Я поменял sapply выше на lapply, поскольку sapply не имеет смысла.

EDIT 2: Если есть способ написать определенную пользователем функцию, которая также будет достаточной

Ответ 1

Кажется, что class(x) <- "factor" не работает, и не делает as(x, "factor"), поэтому я не знаю прямого способа сделать то, что вы хотите.

... Но несколько более явный способ:

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

Несколько вещей: вы можете добавить больше случаев по мере необходимости. И первая строка функции позволяет вам звонить с одним именем класса. Последний "по умолчанию" случай switch вызывает функцию as, и ваш пробег может отличаться.

Ответ 2

Попробуйте следующее:

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

Второй пример. Также попробуйте этот пример (который позволяет использовать NA для любого столбца, класс которого не должен изменяться). Мы загружаем пакет zoo, так как он предоставляет версию as.Date, которая имеет начало по умолчанию, и мы определяем наш собственный as.POSIXct2, чтобы также не указывать происхождение.

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

Обратите внимание, что только при преобразовании чисел в "Date" или "POSIXct", что есть причины возникновения, и при преобразовании символьных строк, таких как "2000-01-01", никакое происхождение не нужно указывать в любом случае, поэтому для таких ситуаций мы не будем нужно загрузить зоопарк, и нам не понадобится наша версия as.POSIXct.

EDIT: добавлен еще один пример.