R -apply- 将多个数值列转换为因子列

8

我需要将许多数字列转换为因子类型。以下是一个示例表格:

df <- data.frame(A=1:10, B=2:11, C=3:12)

我尝试使用apply方法:

cols<-c('A', 'B')
df[,cols]<-apply(df[,cols], 2, function(x){ as.factor(x)});

但结果是一个字符类。

> class(df$A)
[1] "character"

我该如何在不对每列都执行as.factor的情况下完成这个操作?

2
你的想法是正确的,但是apply返回的是一个矩阵,它无法识别因子。但是数据框可以。 - Gary Weissman
6个回答

14
尝试
df[,cols] <- lapply(df[,cols],as.factor)
问题在于apply()试图将结果绑定到矩阵中,这会导致将列强制转换为字符类型:
class(apply(df[,cols], 2, as.factor))  ## matrix
class(as.factor(df[,1]))  ## factor

相比之下,lapply() 操作的是列表中的元素。


4

更新于2017年11月9日

purrr / purrrlyr仍在开发中

与Ben的方法类似,但使用purrrlyr::dmap_at

library(purrrlyr)

df <- data.frame(A=1:10, B=2:11, C=3:12)

# selected cols to factor
cols <- c('A', 'B')

(dmap_at(df, factor, .at = cols))

A        B       C
<fctr>   <fctr>  <int>
1        2       3      
2        3       4      
3        4       5      
4        5       6      
5        6       7      
6        7       8      
7        8       9      
8        9       10     
9        10      11     
10       11      12 

map(df [cols],factor) 行不行?我找不到任何 dmap_at() 函数。 - Seanosapien
你可能是对的。可以理解的是,purrr和相关的包仍在经历许多变化。dmap_at已经移动到了purrrlyr中。http://purrr.tidyverse.org/news/index.html - Tanya Murphy
这就解释了!我一直在使用最新版本的purrr,所以以为我错过了什么。 - Seanosapien

3
您可以将结果放回数据框中,该数据框将识别因子: df[,cols]<-data.frame(apply(df[,cols], 2, function(x){ as.factor(x)}))

感谢您。返回翻译后的文本:结果返回一个矩阵,它们不识别因子。 - GabyLP

2
另一个选项是使用purrrdplyr,可能比基本解决方案更易读,并将数据保留在数据框中:
以下是数据:
df <- data.frame(A=1:10, B=2:11, C=3:12)

str(df)
'data.frame':   10 obs. of  3 variables:
 $ A: int  1 2 3 4 5 6 7 8 9 10
 $ B: int  2 3 4 5 6 7 8 9 10 11
 $ C: int  3 4 5 6 7 8 9 10 11 12

我们可以使用 dmap 轻松操作所有列:
library(purrr)
library(dplyr)

# all cols to factor
dmap(df, as.factor)

Source: local data frame [10 x 3]

        A      B      C
   (fctr) (fctr) (fctr)
1       1      2      3
2       2      3      4
3       3      4      5
4       4      5      6
5       5      6      7
6       6      7      8
7       7      8      9
8       8      9     10
9       9     10     11
10     10     11     12

同样地,使用dplyr中的select函数在列的子集上使用dmap

# selected cols to factor
cols <- c('A', 'B')

df[,cols] <- 
  df %>% 
  select(one_of(cols)) %>% 
  dmap(as.factor)

为了获得所需的结果:
str(df)
'data.frame':   10 obs. of  3 variables:
 $ A: Factor w/ 10 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10
 $ B: Factor w/ 10 levels "2","3","4","5",..: 1 2 3 4 5 6 7 8 9 10
 $ C: int  3 4 5 6 7 8 9 10 11 12

1
一个简单但有效的选择是mapply
df <- data.frame(A=1:10, B=2:11, C=3:12)
cols <- c('A', 'B')

df[,cols] <- as.data.frame(mapply(as.factor,df[,cols]))

你也可以使用 for 循环来实现相同的结果:
for(col in cols){
  df[,col] <- as.factor(df[,col])
}

1

Here are couple of tidyverse options -

library(dplyr)

cols <- c('A', 'B')

df <- df %>% mutate(across(all_of(cols), factor)) 

str(df)

#'data.frame':  10 obs. of  3 variables:
# $ A: Factor w/ 10 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10
# $ B: Factor w/ 10 levels "2","3","4","5",..: 1 2 3 4 5 6 7 8 9 10
# $ C: int  3 4 5 6 7 8 9 10 11 12

使用 map -
df[cols] <- purrr::map(df[cols], factor)

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