基于DataFrame按样本提取首值并计算变化百分比的实现求助
问题描述
我有一个存储不同样本实验数据的DataFrametestdata,需要编写函数提取每个样本指定列的首个值,计算该列各值相对首值的变化百分比并保存到新列。
样本列表
samplename = [smpl_1, smpl_2, smpl_3]
实验数据示例(DataFrame testdata)
sample_ID value1 value2 smpl1 3.5 96 smpl1 3.5 67 sampl2 3.5 92 sampl2 3.5 87
尝试的错误代码
def test_info(samplename, testdata): for sample in samplenames: testdata = testdata.loc[testdata['sample_ID']==sample] first = testdata.loc[(testdata['cycle']==1)][('capacity')].to_numpy() testdata['fading_%'] = (testdata['capacity']) / first * 100 return(testdata)
期望输出
sample_ID value1 value2 change% smpl1 3.5 96 100 smpl1 3.5 67 69.8 sampl2 3.5 92 100 sampl2 3.5 87 94.6
问题分析与修复方案
原代码存在的问题
- 缩进错误:
for循环未包含在函数体内,语法不合法 - 变量名不匹配:函数参数为
samplename,循环中使用未定义的samplenames - 列名不匹配:示例DataFrame无
cycle和capacity列,对应需求的应为value2 - 数据丢失风险:每次循环重新赋值
testdata会覆盖原数据,最终仅保留最后一个样本的数据 - 逻辑冗余:无需通过
cycle==1提取首个值,直接取每组第一行数据即可
修复后的代码
import pandas as pd def calculate_change_percent(testdata, target_col='value2', result_col='change%'): # 按样本分组,为每行匹配对应样本的目标列首个值 first_values = testdata.groupby('sample_ID')[target_col].transform('first') # 计算变化百分比并保留1位小数 testdata[result_col] = round((testdata[target_col] / first_values) * 100, 1) return testdata # 测试示例 if __name__ == '__main__': # 构造示例数据 testdata = pd.DataFrame({ 'sample_ID': ['smpl1', 'smpl1', 'sampl2', 'sampl2'], 'value1': [3.5, 3.5, 3.5, 3.5], 'value2': [96, 67, 92, 87] }) # 调用函数得到结果 result_df = calculate_change_percent(testdata) print(result_df)
代码说明
- 使用
groupby+transform('first')高效为每个样本的所有行匹配目标列首个值,避免低效循环 - 直接在原DataFrame新增结果列,若不想修改原数据,可先执行
testdata.copy()后操作 - 通过
round函数控制百分比小数位数,与期望输出格式一致 - 函数支持自定义目标列和结果列名,适配不同数据分析需求
内容的提问来源于stack exchange,提问作者maruffel
相关产品推荐
相关产品推荐

