问题 为数据帧的“类”提供向量


您知道如何为数据框提供名称向量以更改数据框的列名或行名。是否有类似的方法来提供更改数据框中每列类的名称向量?当您使用colClasses读入带有read.table的数据框时,可以执行此操作。如果在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)

编辑:我改变了lapply,因为sapply没有意义。

编辑2:如果有办法编写用户定义的函数也足够了


8505
2018-02-09 16:32


起源



答案:


它似乎 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 功能和你的里程可能会有所不同


5
2018-02-09 16:59



@ Tommy我希望得到答案“你们已经有了一个可以轻松实现这一目标的基本功能”。你的功能运作良好。我将把它扔进我的.First()作为我自己的便利功能。我真的有点惊讶R-core团队还没有实现过这样的东西,特别是因为它似乎是read.table的一部分。谢谢。 - Tyler Rinker
@Tyler我分享了你的惊喜。我一直在寻找基本功能来做到这一点,并且通常会采取一些临时方法。如果R核心团队会考虑这个问题,那就太棒了。 - digitalmaps


答案:


它似乎 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 功能和你的里程可能会有所不同


5
2018-02-09 16:59



@ Tommy我希望得到答案“你们已经有了一个可以轻松实现这一目标的基本功能”。你的功能运作良好。我将把它扔进我的.First()作为我自己的便利功能。我真的有点惊讶R-core团队还没有实现过这样的东西,特别是因为它似乎是read.table的一部分。谢谢。 - Tyler Rinker
@Tyler我分享了你的惊喜。我一直在寻找基本功能来做到这一点,并且通常会采取一些临时方法。如果R核心团队会考虑这个问题,那就太棒了。 - digitalmaps


尝试这个:

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

第二个例子。也尝试这个例子(允许 NA 用于任何不改变其类的列。我们加载动物园包,因为它提供了一个版本 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 。

编辑:添加了另一个例子。


8
2018-02-09 17:13