如何对含零及小于1值的行运行scipy.stats.gmean并解决报错
问题根因
报错和结果不符合预期的核心原因有3个:
- 数据类型异常:原始数据第四行
GSM774列的值为字符串格式的00000000,导致所有数值列被自动识别为字符串(object)类型,scipy.stats.gmean计算时需要对数值取对数,无法处理字符串类型,直接触发类型报错。 - 列切片范围错误:代码中使用
df.iloc[:,1:5]做切片,pandas的iloc切片为左闭右开规则,仅选中了GSM772到GSM775共4列,漏掉了最后一列GSM776,计算范围不符合要求。 - 未实现自定义计算规则:原生
scipy.stats.gmean不会自动判定行内是否存在零值,无法满足「行内存在零值则几何均值直接记为0」的要求。
最优解决方法
先清洗数据类型,再实现自定义的按行计算逻辑,完整可运行代码如下:
import pandas as pd import numpy as np from scipy.stats import gmean # 第一步:清洗数据类型,将所有GSM样本列转为浮点型,非法值统一转为0 # 先将基因名列设为索引,避免类型转换影响基因名 df = df.set_index('#Gene') # 对所有列做数值转换,无法解析的值转为NaN后填充为0 df = df.apply(pd.to_numeric, errors='coerce').fillna(0) # 第二步:按规则逐行计算几何均值 def row_gmean_calc(row): # 行内存在任意0值,直接返回0 if (row == 0).any(): return 0.0 # 无零值时正常计算几何均值 return gmean(row) # 将计算结果追加为新列 df['GeometricMean'] = df.apply(row_gmean_calc, axis=1) # 如需把基因名从索引还原为普通列,执行下行代码即可 df = df.reset_index() # 打印验证结果 print(df)
额外说明
- 原代码中重复调用2次
scipy.stats.gmean属于冗余计算,无实际作用可删除。 - 类型转换步骤会自动把类似
00000000的字符串格式数字转为合法数值,无需手动逐行替换脏值。 - 计算逻辑严格匹配需求:只要行内存在零值直接返回0,无零值时对整行所有值计算几何均值,不会错误纳入零值参与对数计算。
内容的提问来源于stack exchange,提问作者TraPS-VarI
相关产品推荐
相关产品推荐

