使用tidyverse创建ft数据框时遇‘SM未找到’错误求助
问题描述
我想要创建一个包含un、SM、FDtype、Species、ba、vol、prodvol和n列的ft数据框,但运行tidyverse代码时触发错误:
Error in if_else(vol == 0, "XXX", SM) : object 'SM' not found
已确认原始数据FAT表中存在SM列,且该列类型为character。
使用的tidyverse代码:
ft <- FAT %>% group_by(un, SM, FDtype, Species, .add = FALSE) %>% summarize(ba = sum(ba), vol = sum(vol), prodvol = sum(prodvol), n = sum(nrep)) %>% ungroup() %>% mutate(across(c(ba, vol, prodvol), ~ . * 10)) %>% mutate(ba = if_else(vol == 0, 0, ba), SM = if_else(vol == 0, "XXX", SM))
目前使用ddply的替代代码可正常运行,但希望改用tidyverse实现该逻辑,替代代码如下:
ft <- ddply(FAT, c("un", "SM","FDtype","Species"), function(df)c(sum(df$ba), sum(df$vol), sum(df$prodvol), sum(df$nrep))) ft[ ,c(5,6,7)] <- ft[ ,c(5,6,7)] * 10 colnames(ft) <- list("un", "SM","FDtype","Species", "ba", "vol", "prodvol", "n") ft$ba[ft$vol==0] <- 0 ft$SM[ft$vol==0] <- "XXX"
解决方法
错误的核心原因有两种可能:一是dplyr版本的分组汇总默认行为导致SM列未被正确保留;二是全局环境中存在同名的SM变量,导致代码误引用了环境变量而非数据框列。以下是两种针对性的修复方案:
方案1:明确控制分组汇总后的分组行为
在summarize步骤中指定.groups = "drop",替代后续单独的ungroup()操作,确保所有分组列(包括SM)都被保留在汇总结果中:
ft <- FAT %>% group_by(un, SM, FDtype, Species, .add = FALSE) %>% summarize(ba = sum(ba), vol = sum(vol), prodvol = sum(prodvol), n = sum(nrep), .groups = "drop") %>% # 直接在此取消分组并保留所有分组列 mutate(across(c(ba, vol, prodvol), ~ . * 10)) %>% mutate(ba = if_else(vol == 0, 0, ba), SM = if_else(vol == 0, "XXX", SM))
方案2:明确指定引用数据框内的SM列
如果是全局环境存在同名变量导致的冲突,使用.data pronoun明确指定引用当前数据框中的SM列,避免变量混淆:
ft <- FAT %>% group_by(un, SM, FDtype, Species, .add = FALSE) %>% summarize(ba = sum(ba), vol = sum(vol), prodvol = sum(prodvol), n = sum(nrep)) %>% ungroup() %>% mutate(across(c(ba, vol, prodvol), ~ . * 10)) %>% mutate(ba = if_else(vol == 0, 0, ba), SM = if_else(vol == 0, "XXX", .data$SM)) # 明确引用数据框列
两种方案都可以实现与ddply代码完全一致的逻辑,生成目标结构的ft数据框。
内容的提问来源于stack exchange,提问作者Ajay
相关产品推荐
相关产品推荐

