pandas DataFrame按行做除法归一化时如何保留非数值对象列
解决方法
你原来的代码丢失Sample_name列的核心原因是:切片计算时仅选中了从C14-Cer_mean开始的数值列,没有将非数值的标识列纳入计算范围,只要将标识列和归一化计算结果按列合并即可,两种常用实现如下:
- 方法1:拆分计算后拼接,逻辑最直观
import pandas as pd # 提取数值列,以Blank行对应值做归一化 # 注:不硬编码iloc[-1],通过Sample_name字段匹配Blank行,避免Blank行位置变化导致计算错误 blank_row = df[df['Sample_name'] == 'Blank'].squeeze() norm_value = df.loc[:, 'C14-Cer_mean':].div(blank_row['C14-Cer_mean':]) # 拼接Sample_name列和归一化后的数值列 df_normalized = pd.concat([df[['Sample_name']], norm_value], axis=1)
如果确认Blank行一定是DataFrame最后一行,blank_row可以直接替换为df.iloc[-1],和你原代码的取值逻辑一致。
- 方法2:用
assign批量覆写数值列,无需单独拼接
# 取出所有需要归一化的数值列名 numeric_cols = df.columns[df.columns.get_loc('C14-Cer_mean'):] # 取出Blank行的对应数值 blank_vals = df[df['Sample_name'] == 'Blank'][numeric_cols].iloc[0] # 批量计算归一化值,保留原表所有非数值列 df_normalized = df.assign(**{col: df[col]/blank_vals[col] for col in numeric_cols})
运行结果
两种方法得到的输出结构完全符合需求:
Sample_name C14-Cer_mean C16-Cer_mean C18-Cer_mean C18:1-Cer_mean 0 1 1 0.305224 0.542487 66.428386 73.615331 1 1 10 0.814695 1.246165 73.802656 58.064596 2 1 13 0.556438 0.517383 50.555945 51.913684 3 1 14 0.314057 1.148754 56.165753 61.262199 4 1 5 0.499128 0.460813 40.182432 41.771051 5 1 6 0.300203 0.784065 47.359483 52.842028 6 1 9 0.395581 1.082054 54.019758 58.772851 7 Blank 1.000000 1.000000 1.000000 1.000000
注:你给出的目标示例中
1 9行的C18:1-Cer_mean值存在笔误,实际计算结果为58.77左右,并非8.77。
内容的提问来源于stack exchange,提问作者TraPS-VarI
相关产品推荐
相关产品推荐

