我有150k列的1.05亿个条目,它们要么是"none", "01", "12", "2+"
。遗憾的是,并非所有列都包含所有因素。
。
df <- data.frame(x1 = rep(c("none", "12", "2+"), each = 5),
x2 = rep(c("none", "01", "12"), each = 5)) %>%
data.table::as.data.table()
所以如果我输入
df$x1<-as.integer(as.factor(df$x1))
我得到了和
相同的结果df$x2<-as.integer(as.factor(df$x2))
这不是我想要的。
我可以这样写:
require(magrittr)
df$x1<-factor(df$x1,levels = c("none","01","12","2+")) %>% as.integer()
df$x2<-factor(df$x2,levels = c("none","01","12","2+")) %>% as.integer()
这做的工作,但我有150K列。如果我不能一个一个地处理这些问题,最好的办法是什么?
如果我们想在多个列上应用,使用across
library(dplyr)
df1 <- df %>%
mutate(across(everything(), ~
as.integer(factor(., levels = c("none","01","12","2+"))))
如果我们想忽略第一个,用-
df1 <- df %>%
mutate(across(-1, ~
as.integer(factor(., levels = c("none","01","12","2+"))))
或者使用base R
df[] <- lapply(df, function(x) as.integer(factor(x, levels = c("none","01","12","2+"))))
以下是data.table
解决方案。
对于一个大的数据集,与其调用names(df)
两次,不如只调用一次,在转换df
的列之前赋值,然后使用150K个名称的向量。
library(data.table)
levs <- c("none","01","12","2+")
df[, (names(df)) := lapply(.SD, factor, levels = levs), .SDcols = names(df)]
identical(levels(df$x1), levels(df$x2))
#[1] TRUE
那么现在使用上面的代码将级别强制为整数。
df[, (names(df)) := lapply(.SD, function(x){
as.integer(factor(x, levels = levs))
}), .SDcols = names(df)]