使用mutate(across)将多列转为因子并设水平遇问题求助
问题与解决方案
问题场景
现有如下结构的data.frame(实际包含更多无需修改的列):
dat <- data.frame(Comp1Letter = c("A", "B", "D", "F", "U", "A*", "B", "C"), Comp2Letter = c("B", "C", "E", "U", "A", "C", "A*", "E"), Comp3Letter = c("D", "A", "C", "D", "F", "D", "C", "A")) GradeLevels <- c("A*", "A", "B", "C", "D", "E", "F", "G", "U")
其中Comp1Letter、Comp2Letter、Comp3Letter列为字符类型的字母成绩,需要转换为指定顺序的因子。多次调用mutate的写法可实现需求,但过于冗长:
factordat <- dat %>% mutate(Comp1Letter = factor(Comp1Letter, levels = GradeLevels)) %>% mutate(Comp2Letter = factor(Comp2Letter, levels = GradeLevels)) %>% mutate(Comp3Letter = factor(Comp3Letter, levels = GradeLevels))
尝试用mutate结合across优化时,转换后列仍为字符向量,未成功转为因子:
factordat <- dat %>% mutate(across(c(Comp1Letter, Comp2Letter, Comp3Letter) , factor(levels = GradeLetters)))
问题原因
- 变量名拼写错误:定义的级别向量是
GradeLevels,但优化代码中误写为GradeLetters,R无法找到正确的级别参数,导致因子转换逻辑异常。 across函数传递方式错误:直接传入factor(levels = ...)会立即执行该函数,而非将其作为处理每一列的函数模板。across需要接收的是一个函数(或可转为函数的对象),用于应用到选中的每一列。
正确解决方案
方案1:修正变量名+公式语法(推荐)
利用dplyr的公式语法~定义处理逻辑,.代表当前列:
factordat <- dat %>% mutate(across(c(Comp1Letter, Comp2Letter, Comp3Letter), ~factor(., levels = GradeLevels)))
方案2:匿名函数写法
用标准匿名函数明确指定参数:
factordat <- dat %>% mutate(across(c(Comp1Letter, Comp2Letter, Comp3Letter), function(x) factor(x, levels = GradeLevels)))
方案3:简化列选择(如果列名有规律)
若目标列都以Letter结尾,可使用ends_with批量选择列,进一步简化代码:
factordat <- dat %>% mutate(across(ends_with("Letter"), ~factor(., levels = GradeLevels)))
验证转换结果
执行str(factordat)可查看列类型,确认目标列已转为指定级别的因子:
str(factordat) # 'data.frame': 8 obs. of 3 variables: # $ Comp1Letter: Factor w/ 9 levels "A*","A","B","C",..: 2 3 5 7 9 1 3 4 # $ Comp2Letter: Factor w/ 9 levels "A*","A","B","C",..: 3 4 6 9 2 4 1 6 # $ Comp3Letter: Factor w/ 9 levels "A*","A","B","C",..: 5 2 4 5 7 5 4 2
内容的提问来源于stack exchange,提问作者Alan Nielsen
相关产品推荐
相关产品推荐

