如何修复循环函数使其自动遍历每行计算辛普森多样性?
问题分析与修复方案
我正在处理一个45行6列的数据集(已移除2列无关数据),需要编写函数遍历每行计算辛普森多样性,公式为 D = Σni(ni-1) / N(N-1)(其中n是各列数值,N是该行所有列数值的总和),最终将每行结果存入simp向量。但目前代码运行后只有第一行有有效结果,其余全为0,需修改函数实现全行列遍历计算。
编辑说明:作业要求,不能使用现成的辛普森多样性函数。
原代码与输出
原代码
#我的代码:(killdat是移除两列后的目标数据集) #simp是用于存储结果的空向量 killdat=select(killarney, -Lake, -Status) test=function(x){ simp=vector(mode="logical", length=nrow(Df)) for(j in 1:nrow(Df)){ for(i in 1:ncol(Df)){ abun=(Df[j,i])*(Df[j,i]-1) n=Df[j,] } N=sum(n) num=sum(abun) den=N*(N-1) simp[j]=1-(num/den);return(simp) }} test(killdat)
输出结果
[1] 0.9396795 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 [13] 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 [25] 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 [37] 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
代码问题点
- 参数不匹配:函数定义用
x作为参数,但内部全程引用未定义的Df,依赖全局变量,不符合通用性要求。 - return位置错误:
return(simp)写在第一次外层循环末尾,函数计算完第一行直接返回,后续循环未执行,导致后面的元素都是逻辑向量初始值FALSE(转数值为0)。 - 未累加计算值:内层循环中
abun被每次循环覆盖,最终sum(abun)仅为最后一列的计算值,未累加所有列的结果。 - 向量类型错误:
simp被定义为逻辑型向量,存储数值会自动转换为0/1,应使用数值型向量。
修复后的代码
killdat <- select(killarney, -Lake, -Status) test <- function(Df){ # 初始化数值型向量存储结果 simp <- vector(mode = "numeric", length = nrow(Df)) # 遍历每一行 for(j in 1:nrow(Df)){ # 初始化当前行的累加值为0 abun_sum <- 0 # 遍历当前行的每一列 for(i in 1:ncol(Df)){ ni <- Df[j, i] abun_sum <- abun_sum + ni*(ni - 1) } N <- sum(Df[j, ]) den <- N*(N - 1) # 处理N=0或1的情况,避免除以0错误 if(den == 0){ simp[j] <- 0 } else { simp[j] <- 1 - (abun_sum / den) } } # 所有行计算完成后再返回结果 return(simp) } test(killdat)
修复说明
- 统一函数参数为
Df,确保内部变量引用正确,函数可接收任意符合格式的数据集。 - 将
return(simp)移至外层循环结束后,保证所有行计算完成再返回结果。 - 新增
abun_sum变量,在内层循环中累加当前行所有列的ni(ni-1)值,得到正确的分子总和。 - 将
simp改为数值型向量,避免类型转换错误。 - 增加对
den=0的判断(当该行数值总和为0或1时),防止出现除以0的运行错误。
内容的提问来源于stack exchange,提问作者ecologykiwi
相关产品推荐
相关产品推荐

