一次转换数据框的多个列的类型

Pau*_*yuk 38 r type-conversion

我似乎花了很多时间从文件,数据库或其他东西创建数据帧,然后将每列转换为我想要的类型(数字,因子,字符等).有没有办法一步完成,可能是通过给出一个类型的向量?

foo<-data.frame(x=c(1:10), 
                y=c("red", "red", "red", "blue", "blue", 
                    "blue", "yellow", "yellow", "yellow", 
                    "green"),
                z=Sys.Date()+c(1:10))

foo$x<-as.character(foo$x)
foo$y<-as.character(foo$y)
foo$z<-as.numeric(foo$z)
Run Code Online (Sandbox Code Playgroud)

而不是最后三个命令,我想做类似的事情

foo<-convert.magic(foo, c(character, character, numeric))
Run Code Online (Sandbox Code Playgroud)

jor*_*ran 35

编辑有关基本概念的一些简化和扩展,请参阅相关问题.

我对布兰登答案的评论使用switch:

convert.magic <- function(obj,types){
    for (i in 1:length(obj)){
        FUN <- switch(types[i],character = as.character, 
                                   numeric = as.numeric, 
                                   factor = as.factor)
        obj[,i] <- FUN(obj[,i])
    }
    obj
}

out <- convert.magic(foo,c('character','character','numeric'))
> str(out)
'data.frame':   10 obs. of  3 variables:
 $ x: chr  "1" "2" "3" "4" ...
 $ y: chr  "red" "red" "red" "blue" ...
 $ z: num  15254 15255 15256 15257 15258 ...
Run Code Online (Sandbox Code Playgroud)

对于真正大的数据帧,您可能希望使用lapply而不是for循环:

convert.magic1 <- function(obj,types){
    out <- lapply(1:length(obj),FUN = function(i){FUN1 <- switch(types[i],character = as.character,numeric = as.numeric,factor = as.factor); FUN1(obj[,i])})
    names(out) <- colnames(obj)
    as.data.frame(out,stringsAsFactors = FALSE)
}
Run Code Online (Sandbox Code Playgroud)

执行此操作时,请注意在R中强制数据的一些复杂性.例如,从因子转换为数字通常涉及as.numeric(as.character(...)).此外,要注意data.frame()as.data.frame()S转换性格因素的默认行为.

  • +1推荐`lapply`.我过去一直在努力优化这类问题,事实证明`[< - `操作相当慢. (2认同)

Luk*_*ins 18

如果要自动检测列数据类型而不是手动指定它(例如,在数据整理等之后),该功能type.convert()可能会有所帮助.

该函数type.convert()接受一个字符向量,并尝试确定所有元素的最佳类型(意味着每列必须应用一次).

df[] <- lapply(df, function(x) type.convert(as.character(x)))
Run Code Online (Sandbox Code Playgroud)

既然我爱dplyr,我更喜欢:

library(dplyr)
df <- df %>% mutate_all(funs(type.convert(as.character(.))))
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的格式化提示。我花了很长时间才找到像 type.convert 这样的功能,所以我认为将其放在更频繁出现的类似问题上可以帮助像我这样的人。 (2认同)

Bra*_*sen 7

我发现我也遇到过这个问题.这是关于如何导入数据的.所有read ...()函数都有某种类型的选项来指定不将字符串转换为因子.这意味着文本字符串将保留字符,而看起来像数字的内容将保留为数字.如果元素为空且不是NA,则会出现问题.但同样,na.strings = c("",......)也应解决这个问题.我首先要仔细研究您的导入过程并相应地进行调整.

但是你总是可以创建一个函数并推送这个字符串.

convert.magic <- function(x, y=NA) {
for(i in 1:length(y)) { 
if (y[i] == "numeric") { 
x[i] <- as.numeric(x[[i]])
}
if (y[i] == "character")
x[i] <- as.character(x[[i]])
}
return(x)
}

foo <- convert.magic(foo, c("character", "character", "numeric"))

> str(foo)
'data.frame':   10 obs. of  3 variables:
 $ x: chr  "1" "2" "3" "4" ...
 $ y: chr  "red" "red" "red" "blue" ...
 $ z: num  15254 15255 15256 15257 15258 ...
Run Code Online (Sandbox Code Playgroud)


小智 7

我知道我回答很晚,但是使用循环和属性函数是解决问题的简单方法.

names <- c("x", "y", "z")
chclass <- c("character", "character", "numeric")

for (i in (1:length(names))) {
  attributes(foo[, names[i]])$class <- chclass[i]
}
Run Code Online (Sandbox Code Playgroud)