поставьте вектор для "классов" данных - PullRequest
12 голосов
/ 09 февраля 2012

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

РЕДАКТИРОВАТЬ 2: Если есть способ записипользовательская функция, которой также будет достаточно

Ответы [ 2 ]

8 голосов
/ 09 февраля 2012

Попробуйте это:

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.

РЕДАКТИРОВАТЬ: Добавлен еще один пример.

5 голосов
/ 09 февраля 2012

Кажется, 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, и ваш пробег может отличаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...