我想将包含130多列的整个data.frame
转换为数字。
我知道我需要使用as.numeric
,但问题是我必须单独将这个函数应用于每个130列中的一列。我尝试将其应用于整个data.frame
,但是我收到了以下错误消息:
Error: (list) object cannot be coerced to type 'double'
我该如何用相对较短的代码实现这个功能?
在基本的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
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。 - moodymudskipperlevels
路线。但是,我认为as.numeric(as.character)
更容易理解。 - akrunDF <- 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]”
谢谢n1tk,你的解决方案很有效。我最初尝试使用了这段代码:
for(i in 1:140){
mydata[, i] <- as.numeric(mydata[, i])
}
但我认为你的解决方案更简单。
akrun,是的,我知道我们需要先将因子转换为字符,然后再转换为数字。
n1tk
的代码更快,可以在我的答案中看到基准测试。 - moodymudskipper