如何将整个数据框转换为数字型数据。

10

我想将包含130多列的整个data.frame转换为数字。

我知道我需要使用as.numeric,但问题是我必须单独将这个函数应用于每个130列中的一列。我尝试将其应用于整个data.frame,但是我收到了以下错误消息:

Error: (list) object cannot be coerced to type 'double'

我该如何用相对较短的代码实现这个功能?

你从哪里获取这些数据的?你使用的接口可能有一些工具可以在上游进行转换。 - moodymudskipper
4个回答

15

在基本的R语言中,我们可以做到:

df[] <- lapply(df, as.numeric)
或者
df[cols_to_convert]  <- lapply(df[cols_to_convert], as.numeric)

这是解决方案的基准测试结果(不考虑因素的影响):

DF <- data.frame(a = 1:10000, b = letters[1:10000],
                 c = seq(as.Date("2004-01-01"), by = "week", len = 10000),
                 stringsAsFactors = TRUE)
DF <- setNames(do.call(cbind,replicate(50,DF,simplify = F)),paste0("V",1:150))

dim(DF)
# [1] 10000   150

library(dplyr)
n1tk  <- function(x) data.frame(data.matrix(x))
mm    <- function(x) {x[] <- lapply(x,as.numeric); x}
akrun <- function(x) mutate_all(x, as.numeric)
mo    <- function(x)  {for(i in 1:150){ x[, i] <- as.numeric(x[, i])}}

microbenchmark::microbenchmark(
  akrun = akrun(DF),
  n1tk  = n1tk(DF),
  mo    = mo(DF),
  mm    = mm(DF)
)

# Unit: milliseconds
#   expr      min        lq       mean    median        uq      max neval
#  akrun 152.9837 177.48150 198.292412 190.38610 206.56800 432.2679   100
#   n1tk  10.8700  14.48015  22.632782  17.43660  21.68520  89.4694   100
#     mo   9.3512  11.41880  15.313889  14.71970  17.66530  37.6390   100
#     mm   4.8294   5.91975   8.906348   7.80095  10.11335  71.2647   100

9

dplyr中的选项

library(dplyr)
df1 %>%
   mutate_all(as.numeric)

如果列的类别是factor,则需要先转换为character,再转换为numeric
df1 %>%
    mutate_all(funs(as.numeric(as.character(.)))

请注意,如果任何单元格中都没有 character 元素,则应在 character 列上使用 type.convert

df1 %>%
    mutate_all(funs(type.convert(as.character(.)))

如果效率很重要,一个选择是使用 data.table

library(data.table)
DF1 <- copy(DF) # from other post
system.time({setDT(DF1)
    for(j in seq_along(DF1)) set(DF1, i = NULL, j=j, value = as.numeric(DF1[[j]]))
  })
#   user  system elapsed 
#  0.032   0.005   0.037 

为什么要使用 type.convert?它会更快吗?我通常也会使用 as.numeric(as.character(x)),但似乎最推荐的方式(为了最佳效率)是 as.numeric(levels(f))[f],请参见 https://dev59.com/U3A75IYBdhLWcg3wOGLS。 - moodymudskipper
1
我知道levels路线。但是,我认为as.numeric(as.character)更容易理解。 - akrun

1

将数据框转换为数值矩阵

例如,我们有这个数据框:

DF <- data.frame(a = 1:3, b = letters[10:12],
                  c = seq(as.Date("2004-01-01"), by = "week", len = 3),
                  stringsAsFactors = TRUE)
> DF
  a b          c
1 1 j 2004-01-01
2 2 k 2004-01-08
3 3 l 2004-01-15

要将其转换为数字并作为数据框使用,您可以使用以下方法:

DF2 <- data.frame(data.matrix(DF))
> DF2
  a b     c
1 1 1 12418
2 2 2 12425
3 3 3 12432

Note: you can slice the dataframe columns in need if you want specific columns with, for example: “DF[1:3]”


0

谢谢n1tk,你的解决方案很有效。我最初尝试使用了这段代码:

for(i in 1:140){
  mydata[, i] <- as.numeric(mydata[, i])
}

但我认为你的解决方案更简单。

akrun,是的,我知道我们需要先将因子转换为字符,然后再转换为数字。


这实际上比n1tk的代码更快,可以在我的答案中看到基准测试。 - moodymudskipper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接