Python 使用数据帧数据调用函数时出错(无法将序列转换为<;class';float';>;)

Python 使用数据帧数据调用函数时出错(无法将序列转换为<;class';float';>;),python,pandas,dataframe,Python,Pandas,Dataframe,我有一个期权定价模型(非常简单的Black-Scholes),它可以以这种方式处理数据: In [18]: BS2(100.,100.,1.,.001,.3) Out[18]: 11.96762435837207 功能如下: Black Sholes Function def BS2(S,X,T,r,v): d1 = (log(S/X)+(.001+v*v/2)*T)/(v*sqrt(T)) d2 = d1-v*sqrt(T) return (S*CND(d1)-X

我有一个期权定价模型(非常简单的Black-Scholes),它可以以这种方式处理数据:

In [18]:
BS2(100.,100.,1.,.001,.3)

Out[18]:
11.96762435837207
功能如下:

Black Sholes Function

def BS2(S,X,T,r,v):
    d1 = (log(S/X)+(.001+v*v/2)*T)/(v*sqrt(T))
    d2 = d1-v*sqrt(T)
    return (S*CND(d1)-X*exp(-.001*T)*CND(d2))
我认为这与这个问题无关,但BS2称之为:

Cumulative normal distribution function

def CND(X):
    (a1,a2,a3,a4,a5) = (0.31938153, -0.356563782, 1.781477937, 
     -1.821255978, 1.330274429)
    L = abs(X)
    K = 1.0 / (1.0 + 0.2316419 * L)
    w = 1.0 - 1.0 / sqrt(2*pi)*exp(-L*L/2.) * (a1*K + a2*K*K + a3*pow(K,3) +
    a4*pow(K,4) + a5*pow(K,5))
    if X<0:
        w = 1.0-w
    return w
我的数据非常直截了当:

In [13]:
df

Out[13]:
    S    X   T    r    v
0  100  100  1  0.001  0.3
1   50   50  1  0.001  0.3
他们都是64岁

In [14]:

df.dtypes
Out[14]:
S    float64
X    float64
T    float64
r    float64
v    float64
dtype: object
在发送到BS2之前,我还尝试将df变量分配给一个名称(我是这样做的,没有分配:

S=df['S']
X=df['X']
T=df['T']
r=df['r']
v=df['v']
冒着发送太多信息的风险,以下是错误消息:

In [18]:

BS(df)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-18-745e7dd0eb2c> in <module>()
----> 1 BS(df)

<ipython-input-17-b666a39cd530> in BS(df)
  3 def BS(df):
  4     CallPutFlag='c'
----> 5     d1 = (log(S/X)+(.001+v*v/2)*T)/(v*sqrt(T))
  6     d2 = d1-v*sqrt(T)
  7     cp = ((S*CND(d1)-X*exp(-.001*T)*CND(d2)))

C:\Users\camcompco\AppData\Roaming\Python\Python34\site-   packages\pandas\core\series.py in wrapper(self)
 74             return converter(self.iloc[0])
 75         raise TypeError(
---> 76             "cannot convert the series to {0}".format(str(converter)))
 77     return wrapper
 78 

TypeError: cannot convert the series to <class 'float'>
[18]中的

BS(df)
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
---->1 BS(df)
在BS(df)中
3个def BS(df):
4 CallPutFlag='c'
---->5d1=(对数(S/X)+(0.001+v*v/2)*T)/(v*sqrt(T))
6 d2=d1-v*sqrt(T)
7 cp=((S*CND(d1)-X*exp(-0.001*T)*CND(d2)))
C:\Users\camcompco\AppData\Roaming\Python34\site-packages\pandas\core\series.py在包装器中(self)
74返回转换器(self.iloc[0])
75上升类型错误(
--->76“无法将序列转换为{0}”。格式(str(converter)))
77返回包装器
78
TypeError:无法将序列转换为
如蒙协助,将不胜感激


John

我认为使用dataframe.apply()会更容易

然后语法将是
df.apply(func,axis=1)
将函数func应用于每一行

这个问题的答案是类似的:


@JonD的答案很好,但如果数据帧的行数超过几行,这里有一个更快的替代答案:

from scipy.stats import norm

def BS2(df):
    d1 = (np.log(df.S/df.X)+(.001+df.v*df.v/2)*df['T'])/(df.v*np.sqrt(df['T']))
    d2 = d1-df.v*np.sqrt(df['T'])
    return (df.S*norm.cdf(d1)-df.X*np.exp(-.001*df['T'])*norm.cdf(d2))
变化:

  • 要点是对函数进行矢量化。语法方面的主要更改是显式使用numpy版本的
    sqrt
    log
    exp
    。否则,您不必做太多更改,因为numpy/pandas以元素方式支持基本的数学运算
  • 将用户编写的CND替换为scipy的
    norm.cdf
    。更快的b/c内置函数几乎总是尽可能快
  • 这是次要的,但是我在
    df.X
    和其他一些上使用了快捷符号,但是
    df['T']
    需要写出,因为
    df.T
    会被解释为
    df.transpose()
    。我想这是一个很好的例子,说明为什么你应该避免使用快捷符号,但我很懒

  • 顺便说一句,如果你想要更快的速度,下一步要尝试的是用numpy而不是熊猫。你还可以检查其他人是否已经编写了Black-Scholes函数/库(可能,尽管我对此一无所知).

    Hi JohnE,虽然我认为这一特定情况下的速度不会是一个问题,但我在回顾测试算法时确实看到未来需要更高效的代码。你介意通过一个简单的例子详细说明你的意思吗?同样,JonD提供的方法目前还不错,只是出于“知识的考虑”。多亏了你们两位,尼斯回答和我都投了赞成票,但有一点需要注意:这在较大的数据集上可能会很慢。更难(但更有效)的方法是将函数矢量化。@John我添加了一个明确显示这一点的答案。只需将代码更改为您的建议,效果非常好!!
    from scipy.stats import norm
    
    def BS2(df):
        d1 = (np.log(df.S/df.X)+(.001+df.v*df.v/2)*df['T'])/(df.v*np.sqrt(df['T']))
        d2 = d1-df.v*np.sqrt(df['T'])
        return (df.S*norm.cdf(d1)-df.X*np.exp(-.001*df['T'])*norm.cdf(d2))