提问人:user22908408 提问时间:11/13/2023 更新时间:11/13/2023 访问量:57
将函数应用于 pandas 数据帧的每一行,但工作不太正常
Applying a function to each row of a pandas dataframe, not working quite right
问:
我对熊猫生疏了,请温柔一点!
我有一个数据帧,它是 (349, 17) 各种水样值(pH、盐度、温度等)。我正在使用 PyCO2SYS 工具箱来计算化学输出。我创建了一个函数,该函数应使用数据帧行索引,从与行关联的指定列中提取变量,并返回所需的变量(使用 PyCO2SYS)。
函数如下:
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
注意:其他参数是全局定义的;函数中的那些是将随每一行而变化的那些
我想对每个行索引使用此函数,以创建我想要的值的列。我已经能够以一种笨拙的方式做到这一点,但我想优化它。我这样做的一种方法是根据该索引将我的函数应用于每一行:
df['pCO2_out (μatm)'] = df.apply(lambda row: pCO2_column(df.index), axis=0)
但是,当我第一次运行它时,它给了我以下错误: ValueError: Wrong number of items passed 17, placement means 1
如果我将其更改为 axis=1,则每行都包含数组中为所有行计算的每个有价值的内容。
(https://i.stack.imgur.com/5QaMH.png)
如果我将其改回 axis=0,它会正确填充,每行中只有一个唯一值。
(https://i.stack.imgur.com/qkaAM.png)
我知道我还可以遍历每一行,用值填充数组,然后将该数组作为新列插入......
这看起来非常简单,但我不知道我哪里出错了。有什么建议吗?
答:
您错误地构建了 lambda 函数,请查看文档或在线查看一些示例。
具体来说,您不需要按索引进行迭代,因为您已经获得了每一行。要使用最小示例修复代码,请参阅以下内容:axis=1
df_p = pd.DataFrame({'pH':np.random.random(10)})
def pCO2_column(row):
# input variables
PAR2 = row['pH']
return PAR2
df_p.apply(pCO2_column, axis=1)
请注意,我不需要行索引,只需选择列作为行将是一个系列
使用迭代数据帧来运行函数,其中仅传递索引,然后在迭代函数中查询日期帧是非常昂贵且不必要的。apply()
相反,您可以将整行传递给 apply 中的函数:
def pCO2_column(row):
# input variables
PAR1 = row['TA (umol/kg)'] # ALK
PAR2 = row['pH'] # pH
SAL = row['Sal psu'] # Salinity
TEMPIN = row['Temp C'] # Temperature (input)
TEMPOUT = TEMPIN # Temperature (output)
PRESIN = row['Pressure psi a'] # 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
df['pCO2_out (μatm)'] = df.apply(lambda row: pCO2_column(row), axis=1)
下面的例子有效吗?它一次性提供所有行。pyco2.sys
import pandas as pd
#Synthetic data
df = pd.DataFrame(
{'chlor': [2, 1, 1],
'cond': [11, 23, 44],
'depth': [33, 55, 77]},
)
df
#Mock implementation. Replace with actual import.
class pyco2:
def __init__(self):
pass
def sys(par1, par2, par3):
return par1 * par2 / par3
#Create new col in one go
# p2co2.sys docs say it accepts arrays for each argument,
# so you can feed all rows in at once
df['pCO2_out (uatm)'] = pyco2.sys(par1=df['chlor'], par2=df['cond'], par3=df['depth'])
df
评论