如何将整个数据框转换为数字,同时保留小数位?

39

我有一个混合类型的数据框(包含数值和因子变量),我想将整个数据框转换为数值型。以下是我正在处理的数据类型以及遇到的问题:

> a = as.factor(c(0.01,0.02,0.03,0.04))
> b = c(2,4,5,7)
> df1 = data.frame(a,b)
> class(df1$a)
[1] "factor"
> class(df1$b)
[1] "numeric"

当我尝试将整个数据框转换为数字时,它会改变数字的值。例如:

> df2 = as.data.frame(sapply(df1, as.numeric))
> class(df2$a)
[1] "numeric"
> df2
  a b
1 1 2
2 2 4
3 3 5
4 4 7

在本网站的以前帖子中,建议使用as.numeric(as.character(df1$a)),这对于单个列非常有效。但是,我需要将此方法应用于可能包含数百列的数据框。

在保留数值小数的同时,如何将整个数据框从因子转换为数字?

以下是我想要生成的输出,其中ab是数字:

     a b
1 0.01 2
2 0.02 4
3 0.03 5
4 0.04 7

我已经阅读了以下相关帖子,虽然它们都不直接适用于这种情况:

  1. 如何在R中将因子变量转换为数字并保留数字。这个帖子参考了数据框架中的一列。
  2. 从字符转换为数字数据框架。这篇文章没有考虑小数值。
  3. 如何将包含小数的因子列转换为数字?。这仅适用于数据框架中的一列。

6
很好的提问方式。这个问题可能会有所帮助。这是使用factor变量时常见的困扰来源。 - ilir
4个回答

32

使用 dplyr(类似于sapply..)

df2 <- mutate_all(df1, function(x) as.numeric(as.character(x)))

提供:

glimpse(df2)
Observations: 4
Variables: 2
$ a <dbl> 0.01, 0.02, 0.03, 0.04
$ b <dbl> 2, 4, 5, 7

来自您的df1,其内容为:

glimpse(df1)
Observations: 4
Variables: 2
$ a <fctr> 0.01, 0.02, 0.03, 0.04
$ b <dbl> 2, 4, 5, 7

28

你可能需要进行一些检查。不能直接将因子转换为数字类型,必须先应用as.character函数后再进行转换。否则,因子将被转换为其数字存储值。我建议使用is.factor对每列进行检查,如有必要,则进行强制转换为数字类型。

df1[] <- lapply(df1, function(x) {
    if(is.factor(x)) as.numeric(as.character(x)) else x
})
sapply(df1, class)
#         a         b 
# "numeric" "numeric" 

或者在循环外执行以下操作:is_factor <- vapply(df1, is.factor, logical(1)); df1[is_factor] <- ... - hadley
@hadley - 我一直在思考这个问题。先检查,然后在子集上运行更有效吗?而不是在lapply循环内部进行检查? - Rich Scriven
考虑到典型数据集的大小,我怀疑这不会有太大差别。 - hadley

10
df2 <- data.frame(apply(df1, 2, function(x) as.numeric(as.character(x))))

4
> df2 <- data.frame(sapply(df1, function(x) as.numeric(as.character(x))))
> df2
     a b
1 0.01 2
2 0.02 4
3 0.03 5
4 0.04 7
> sapply(df2, class)
        a         b 
"numeric" "numeric" 

1
我可能错了,但这会将一个数字列转换为字符,然后再次转换为数字吗? - Rich Scriven
@RichardScriven认为这是正确的。我认为我的答案也存在同样的问题,但我不认为这是特别严重的。 - n8sty
@n8sty 不,这并不成问题,但似乎有点浪费。 - Rich Scriven

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