为Pandas DataFrame每行应用自定义函数异常,求解决方案
问题描述
现有形状为(349, 17)的水样参数DataFrame(包含pH、盐度、温度等指标),需用PyCO2SYS工具计算化学输出值。已编写自定义函数pCO2_column,通过行索引提取每行变量并返回目标计算值:
def pCO2_column(i): # input variables PAR1 = df['TA (umol/kg)'][i] # ALK PAR2 = df['pH'][i] # pH SAL = df['Sal psu'][i] # Salinity TEMPIN = df['Temp C'][i] # Temperature (input) TEMPOUT = TEMPIN # Temperature (output) PRESIN = df['Pressure psi a'][i] # Pressure (input) PRESOUT = PRESIN # Pressure (output) # Result I want to add into column pCO2_out = pyco2.sys(PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT, pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS)["pCO2_out"] return pCO2_out
注:PAR1TYPE、PAR2TYPE等参数已全局定义,仅函数内变量随每行变化。
尝试用apply生成新列时出现问题:
df['pCO2_out (μatm)'] = df.apply(lambda row: pCO2_column(df.index), axis=0)
运行报错:ValueError: Wrong number of items passed 17, placement implies 1;改为axis=1时,每行返回所有行的计算值数组;改回axis=0虽能填充,但想寻求更优实现,避免循环遍历的低效方式。
问题原因
apply参数逻辑错误:axis=0表示按列处理,此时传入df.index会让函数一次性计算所有行的结果,返回长度为349的数组,但按列处理要求每个列的结果长度匹配列的行数(17),因此触发报错。axis=1时的调用错误:改成axis=1后,lambda中的row是单行数据,但你仍调用pCO2_column(df.index)传入所有行索引,导致函数返回全量结果数组,而非当前行的单个值。- 函数依赖全局DataFrame:
pCO2_column直接引用全局df,没有利用apply传递的单行数据,无法实现逐行计算。
优化方案
方案1:适配apply(axis=1)的逐行计算
调整函数接收单行数据,而非索引,直接用apply按行处理:
def pCO2_column(row): PAR1 = row['TA (umol/kg)'] PAR2 = row['pH'] SAL = row['Sal psu'] TEMPIN = row['Temp C'] TEMPOUT = TEMPIN PRESIN = row['Pressure psi a'] PRESOUT = PRESIN return pyco2.sys(PAR1, PAR2, PAR1TYPE, PAR2TYPE, SAL, TEMPIN, TEMPOUT, PRESIN, PRESOUT, pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS)["pCO2_out"] # 生成新列 df['pCO2_out (μatm)'] = df.apply(pCO2_column, axis=1)
此方式让apply将每行数据传入函数,返回单个值直接填充到新列,逻辑清晰且符合Pandas用法。
方案2:向量化计算(最优解)
PyCO2SYS支持直接传入数组进行向量化计算,无需逐行处理,效率远高于apply或循环:
# 直接传入整列数据进行批量计算 results = pyco2.sys( df['TA (umol/kg)'], df['pH'], PAR1TYPE, PAR2TYPE, df['Sal psu'], df['Temp C'], df['Temp C'], # TEMPOUT与TEMPIN一致 df['Pressure psi a'], df['Pressure psi a'], # PRESOUT与PRESIN一致 pHSCALEIN, K1K2CONSTANTS, KSO4CONSTANTS ) # 提取结果列到DataFrame df['pCO2_out (μatm)'] = results["pCO2_out"]
向量化计算利用了底层优化,避免了Python层面的循环开销,是处理此类批量计算的最优方式。
内容的提问来源于stack exchange,提问作者user22908408
相关产品推荐
相关产品推荐

