为何as.factor与apply联用失效,改用lapply却可行?
为什么
apply转factor失败,lapply却成功? 核心差异:处理数据框的底层逻辑不同
apply的行为:当你用apply(df, 2, as.factor)时,apply会先把数据框转换成矩阵(它本来就是为矩阵设计的工具)。矩阵要求所有元素类型必须统一,如果原数据框的列是字符、整数等混合类型,转成矩阵后会被强制统一为字符型。之后apply对每一列执行as.factor,得到的结果是一个字符矩阵,再用data.frame()包裹后,这些列依然是字符类型,并没有真正变成factor——这就是转换失效的原因。lapply的行为:数据框本质是「由列组成的列表」,lapply会直接遍历数据框的每一列(也就是列表的每个元素),单独对每一列执行as.factor,返回的是一个由factor对象组成的列表。用data.frame()把这个列表转成数据框后,每一列自然就是factor类型,所以转换成功。
举个简单例子验证
假设我们有一个小数据框:
df <- data.frame(a = c(1,2,3), b = c("x", "y", "z"), stringsAsFactors = FALSE)
用apply处理:
apply(df, 2, as.factor) # 输出是矩阵,元素全为字符: # a b # [1,] "1" "x" # [2,] "2" "y" # [3,] "3" "z" class(apply(df, 2, as.factor)) # 结果是"matrix"
转成data.frame后,列还是字符型:
df_apply <- data.frame(apply(df, 2, as.factor)) sapply(df_apply, class) # 输出 a: "character", b: "character"
用lapply处理:
lapply(df, as.factor) # 输出是列表,每个元素都是factor: # $a # [1] 1 2 3 # Levels: 1 2 3 # # $b # [1] x y z # Levels: x y z
转成data.frame后,列都是factor:
df_lapply <- data.frame(lapply(df, as.factor)) sapply(df_lapply, class) # 输出 a: "factor", b: "factor"
总结
- 处理数据框的列类型转换时,优先用
lapply(或者purrr::map这类列表遍历工具),它们会保留每一列的独立类型,不会强制转成矩阵导致类型丢失。 apply更适合处理矩阵,用来处理数据框列很容易因为类型统一的规则产生意外结果。
内容的提问来源于stack exchange,提问作者Taek Hwang
相关产品推荐
相关产品推荐

