使用dplyr计算考古骨骼completeness_MNE时的函数运行报错
代码错误定位
- 第一级筛选逻辑完全反向(级联报错的核心诱因)
原代码的筛选条件is.na(Zone1) & ... & is.na(Zone9)会把「所有测量分区全空的无效样本」全部保留,把有有效测量值的正常样本全部剔除。这些被保留的无效行,PERCENT、ELEMENT、SIDE、Scientific Name等核心字段几乎全为缺失值:- 后续
mutate生成pComplete时,因为PERCENT全为NA,case_when无法生成有效分类值,pComplete全为NA - 执行
filter(pComplete == "Complete")时,所有NA值会被全部剔除,数据集变为0行的空表 - 空表内无任何有效列,后续操作会连续触发「变量未定义」「select参数无效」的报错
- 后续
- 分组计数逻辑冗余
先手动group_by再调用count的写法会重复叠加分组维度,和最终需要的「物种-骨骼元素-侧方位计数」目标不匹配,也容易导致后续select环节找不到计数列。 - 匹配规则易失效
硬编码小写的SIDE匹配值,如果数据集内实际存储的是首字母大写的格式(如"Left"/"Right"),会把所有有效样本全部剔除,再次形成空表触发报错。
可正常运行的修正方案
注意:运行前请确认已经加载dplyr包,并且
data为你实际加载的考古骨骼数据集对象
completeness_MNE <- data %>% # 剔除所有Zone1-Zone9全空的样本(保留至少1个分区有非空值的行) filter(if_any(`Zone 1`:`Zone 9`, ~ !is.na(.x))) %>% # 剔除骨骼完整度低于50%的样本 filter(PERCENT >= 50) %>% # 大小写不敏感匹配有效侧方位值,避免因数据格式差异筛选空表 filter(str_detect(SIDE, regex("axial|both|left|right", ignore_case = TRUE))) %>% # 生成骨骼元素+侧方位的组合标签,清理多余空格 mutate(Element_Side = str_squish(paste(ELEMENT, SIDE))) %>% # 按维度分组计数,直接将计数列命名为MNE count(`Scientific Name`, ELEMENT, Element_Side, name = "MNE") %>% # 输出最终需要的列 select(`Scientific Name`, Element_Side, MNE)
方案优化说明
- 用
if_any()替代冗长的9个is.na()判断,减少列名写错的概率 - 去掉冗余的
pComplete中间变量(需求仅要求保留完整度≥50%的样本,无需额外生成分类标签存入结果) - 用大小写不敏感的正则匹配SIDE值,适配数据的实际存储格式
- 依赖
count自身的分组计数逻辑,去掉手动提前group_by的冗余操作,从根源上避免select环节找不到计数列的报错 - 用
str_squish()清理组合标签的多余空格,避免因空格不一致导致的计数分散
内容的提问来源于stack exchange,提问作者Katharine Thompson
相关产品推荐
相关产品推荐

