Снабдить вектор "классами" кадра данных
Вы знаете, как вы можете предоставить вектор имен для фрейма данных, чтобы изменить имена столбцов или строк в кадре данных. Есть ли аналогичный метод для подачи вектора имен, который изменяет класс каждого столбца в фрейме данных? Это можно сделать, когда вы читаете в 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: добавлен еще один пример.