使用 lambda 应用和不使用 lambda 应用

apply with lambda and apply without lambda

我正在尝试在 df_spx.apply() 中使用 impliedVolatility 函数,同时对变量输入进行硬编码 SKrpriceTpayoffc_or_p

然而,它不起作用,使用相同的功能impliedVolatility,只做lambda + apply它起作用。

[代码 link][1]

# first version of code 

S = SPX_spot
K = df_spx['strike_price']
r = df_spx['r']
price = df_spx['mid_price']
T = df_spx['T_years']
payoff = df_spx['cp_flag']
c_or_p = df_spx["cp_flag"]

df_spx["iv"] = df_spx.apply(impliedVolatility(c_or_p, S, K, T, r,price),axis=1)


# second version of code 

df_spx["impliedvol"] = df_spx.apply(
    lambda r: impliedVolatility(r["cp_flag"],
                                S,
                                r["strike_price"],
                                r['T_years'],    
                                r["r"],
                                r["mid_price"]), 
    axis = 1)
[1]: https://i.stack.imgur.com/yBfO5.png

你必须给apply一个它可以调用的函数。它需要一个可调用的函数。在你的第一个例子中

df_spx.apply(impliedVolatility(c_or_p, S, K, T, r,price), axis=1)

您将函数的结果作为要应用的参数。那是行不通的。如果你改为写

df_spx.apply(impliedVolatility, c_or_p=c_or_p, S=S, K=K, T=T, r=r, price=price, axis=1)

如果函数关键字参数具有相同的名称,或者如果您编写了

df_spx.apply(impliedVolatility, args=(c_or_p, S, K, T, r,price), axis=1)

那么它可能会起作用。请注意,我们没有在应用程序中调用 impliedVolatility。我们将函数作为参数提供。

已经有一个很好的答案,但也许要给它一个不同的视角。 apply 将循环处理您的数据并调用您提供的函数。

假设你有:

import pandas as pd
df = pd.DataFrame({"a": [1, 2, 3], "b": list("asd")})
df
Out: 
   a  b
0  1  a
1  2  s
2  3  d

如果您想创建新数据或对任何列执行某些工作(您也可以在整个行级别执行此操作,顺便说一句,这是您的用例,但现在让我们简化一下)您可以考虑使用申请。假设您只想将每个输入乘以二:

def multiply_by_two(val):
    return val * 2

df.b.apply(multiply_by_two)  # case 1
Out: 
0    aa
1    ss
2    dd

df.a.apply(multiply_by_two)  # case 2
Out: 
0    2
1    4
2    6

第一个用法示例将您的一个字母字符串转换为两个相等的字母字符串,而第二个用法示例很明显。你应该避免在第二种情况下使用 apply,因为它是一个简单的数学运算,与 df.a * 2 相比会非常慢。因此,我的经验法则是:在对非数字对象执行操作时使用 apply(案例 1)。 注意:在这种简单的情况下实际上不需要 lambda。

那么 apply 所做的就是将系列中的每个元素传递给函数。 现在,如果你 apply 在整个数据帧上,传递的值将是一个数据切片作为一个系列。因此,要正确应用您的函数,您需要映射输入。例如:

def add_2_to_a_multiply_b(b, a):
    return (a + 2) * b

df.apply(lambda row: add_2_to_a_multiply_b(*row), axis=1)  # ERROR because the values are unpacked as (df.a, df.b) and you can't add integers and strings (see `add_2_to_a_multiply_b`)

df.apply(lambda row: add_2_to_a_multiply_b(row['b'], row['a']), axis=1)
Out: 
0      aaa
1     ssss
2    ddddd

从这一点开始,您可以构建更复杂的实现,例如,使用 partial 函数等。例如:

def add_to_a_multiply_b(b, a, *, val_to_add):
    return (a + val_to_add) * b

import partial
specialized_func = partial(add_to_a_multiply_b, val_to_add=2)
df.apply(lambda row: specialized_func(row['b'], row['a']), axis=1)

再次强调一下,如果你渴望性能,请避免apply

# 'OK-ISH', does the job... but
def strike_price_minus_mid_price(strike_price, mid_price):
    return strike_price - mid_price

new_data = df.apply(lambda r: strike_price_minus_mid_price(r["strike_price"], r["mid_price"] ), axis=1)

'BETTER'
new_data = df["strike_price"] - df["mid_price"]