You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R4.2.0运行自定义Beta_NTI函数报条件长度大于1错误咨询

问题背景

在R 4.2.0版本中定义了用于计算加权betaNTI的Beta_NTI函数,相同代码在R 4.1.0版本可正常运行,在R4.2.0中执行调用命令时抛出错误。

  • 原函数代码:
Beta_NTI<-function(phylo,comun,beta.reps=999){
  require(picante)
  match.phylo.comun = match.phylo.data(phylo, t(comun))
  beta.mntd.weighted = as.matrix(comdistnt(t(match.phylo.comun$data),cophenetic(match.phylo.comun$phy),abundance.weighted=T))
  
  rand.weighted.bMNTD.comp = array(c(-999),dim=c(ncol(match.phylo.comun$data),ncol(match.phylo.comun$data),beta.reps))
  for (rep in 1:beta.reps) {
    rand.weighted.bMNTD.comp[,,rep] = as.matrix(comdistnt(t(match.phylo.comun$data),taxaShuffle(cophenetic(match.phylo.comun$phy)),abundance.weighted=T,exclude.conspecifics = F))
    print(c(date(),rep))
  }
  weighted.bNTI = matrix(c(NA),nrow=ncol(match.phylo.comun$data),ncol=ncol(match.phylo.comun$data))
  for(columns in 1:(ncol(match.phylo.comun$data)-1)) {
    for(rows in (columns+1):ncol(match.phylo.comun$data)) {
      rand.vals = rand.weighted.bMNTD.comp[rows,columns,];
      weighted.bNTI[rows,columns] = (beta.mntd.weighted[rows,columns] - mean(rand.vals)) / sd(rand.vals)
      rm("rand.vals")
    }
  }
  rownames(weighted.bNTI) = colnames(match.phylo.comun$data);
  colnames(weighted.bNTI) = colnames(match.phylo.comun$data);
  return(as.dist(weighted.bNTI))
}
  • 调用命令:Beta_NTI(bac_tree,t(bac))
  • 报错信息:Error in if (dataclass == "data.frame") { : the condition has length > 1
  • 输入参数说明:bac_tree为系统发育树对象,bac为OTU表,列名为样本ID、行名为OTU编号。
报错原因

R 4.2.0版本调整了if语句的校验规则:R4.1.0及更早版本中,若if的判断条件为长度大于1的逻辑向量,会默认取第一个元素执行判断,仅输出警告;R4.2.0及之后版本不再保留该兼容逻辑,只要判断条件长度不为1就会直接抛出错误。
本次报错的触发逻辑是:

  1. 多数用户读取OTU表时会用tidyverse包的read_*函数,读入的bac是tbl_df(tibble)类型,该类型的class属性为长度3的向量c("tbl_df","tbl","data.frame"),而非基础data.frame的长度1的class值"data.frame"。
  2. picante包内部的类型判断语句if (dataclass == "data.frame")直接拿多长度的class向量做相等判断,得到长度大于1的逻辑向量,在R4.2.0中直接触发报错。
  3. 存在冗余转置问题:函数内部已经对输入的comun参数做了一次转置来匹配match.phylo.data的格式要求,调用时提前对bac做转置属于多余操作,会放大数据类型异常的概率。
修复方案

按以下步骤调整即可正常运行:

  1. 去掉调用时的冗余转置,直接传入原始OTU表,调用命令改为:Beta_NTI(bac_tree, bac)
  2. 在函数内强制将匹配后的群落数据转为基础data.frame格式,消除多类属性的影响,修改后的完整函数代码如下:
Beta_NTI<-function(phylo,comun,beta.reps=999){
  require(picante)
  match.phylo.comun = match.phylo.data(phylo, t(comun))
  # 强制转换为基础data.frame,避免tibble等数据类型导致的判断报错
  match.phylo.comun$data <- as.data.frame(match.phylo.comun$data)
  beta.mntd.weighted = as.matrix(comdistnt(t(match.phylo.comun$data),cophenetic(match.phylo.comun$phy),abundance.weighted=T))
  
  rand.weighted.bMNTD.comp = array(c(-999),dim=c(ncol(match.phylo.comun$data),ncol(match.phylo.comun$data),beta.reps))
  for (rep in 1:beta.reps) {
    rand.weighted.bMNTD.comp[,,rep] = as.matrix(comdistnt(t(match.phylo.comun$data),taxaShuffle(cophenetic(match.phylo.comun$phy)),abundance.weighted=T,exclude.conspecifics = F))
    print(c(date(),rep))
  }
  weighted.bNTI = matrix(c(NA),nrow=ncol(match.phylo.comun$data),ncol=ncol(match.phylo.comun$data))
  for(columns in 1:(ncol(match.phylo.comun$data)-1)) {
    for(rows in (columns+1):ncol(match.phylo.comun$data)) {
      rand.vals = rand.weighted.bMNTD.comp[rows,columns,];
      weighted.bNTI[rows,columns] = (beta.mntd.weighted[rows,columns] - mean(rand.vals)) / sd(rand.vals)
      rm("rand.vals")
    }
  }
  rownames(weighted.bNTI) = colnames(match.phylo.comun$data);
  colnames(weighted.bNTI) = colnames(match.phylo.comun$data);
  return(as.dist(weighted.bNTI))
}
  1. (可选稳妥操作)传参前可将OTU表强制转换为基础矩阵格式,进一步规避数据类型问题:
bac <- as.matrix(bac)
# 再执行函数调用
bNTI_res <- Beta_NTI(bac_tree, bac)

内容的提问来源于stack exchange,提问作者K J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:30:55