dplyr mutate报invalid 'length' argument错误及结果异常求解
问题描述
运行可复现代码时,执行到计算ClassDecrease字段的最后一段mutate语句前所有逻辑均可正常运行,执行该语句时会触发invalid 'length' argument报错,且输出结果不符合预期:
ClassDecrease字段预期输出:
0 0 0 0 0 -1
- 当前实际输出:
0 0 0 0 1 1
完整问题复现代码如下:
library(dplyr) data <- data.frame( Element = c("D","D","R","D","C","C"), SplitCode = c(0,0,0,0,1,1) ) Class_to_Count <- 1 excelCopy <- data %>% group_by(Element) %>% mutate(PreSplitClass = row_number()) %>% ungroup() %>% mutate(ClassAtSplit = case_when( SplitCode == 0 ~ as.integer(0), # This eliminates checking for > 0 SplitCode > lag(SplitCode) ~ PreSplitClass, # if > previous value SplitCode == lag(SplitCode) ~ lag(PreSplitClass) # if equal (0s are avoided) ) ) %>% mutate( LowClassSplit = case_when( SplitCode > lag(SplitCode) & SplitCode == Class_to_Count ~ PreSplitClass, SplitCode == lag(SplitCode) & SplitCode == Class_to_Count ~ lag(PreSplitClass), TRUE ~ 0L ) ) %>% mutate( GrossSubclass = case_when( LowClassSplit == Class_to_Count ~ PreSplitClass, TRUE ~ 0L ) ) %>% group_by(Element) %>% mutate(NetSubclass = cumsum(LowClassSplit == Class_to_Count) ) %>% ungroup %>% rowwise() %>% mutate( ClassSubclass = sum(LowClassSplit, NetSubclass/10) ) %>% ungroup %>% mutate(ApplyToNoSplits = ClassSubclass[match(PreSplitClass, GrossSubclass)] * !SplitCode) %>% ungroup %>% # 报错位置 mutate(ClassDecrease = case_when( LowClassSplit == Class_to_Count ~ (integer(trunc(ClassSubclass)) - PreSplitClass), TRUE ~ 0L ) ) print.data.frame(excelCopy)
问题原因
报错和结果偏差的核心是误用了R的integer()函数:
integer(n)的作用是生成长度为n、元素全为0的整数向量,要求传入的参数是合法的向量长度值- 代码中写的
integer(trunc(ClassSubclass)),相当于把trunc(ClassSubclass)的计算结果作为向量长度传入,当传入值不符合长度参数要求时就会触发长度参数无效报错,计算逻辑也完全偏离预期
此处实际需求是将trunc(ClassSubclass)的计算结果转换为整数类型,应该使用as.integer()函数而非integer()。
修复方案
将计算ClassDecrease部分的integer()替换为as.integer()即可,修改后的对应代码段如下:
mutate(ClassDecrease = case_when( LowClassSplit == Class_to_Count ~ (as.integer(trunc(ClassSubclass)) - PreSplitClass), TRUE ~ 0L ) )
替换后运行代码不会触发报错,ClassDecrease字段输出和预期完全一致。
内容的提问来源于stack exchange,提问作者Curious Jorge - user9788072
相关产品推荐
相关产品推荐

