Pandas Creating Normal Dist系列

时间:2018-01-20 00:09:47

标签: pandas normal-distribution

我正在尝试将excel“正态分布”公式转换为python。

(1-NORM.DIST(A + COL,B,C,TRUE))/(1-NORM.DIST(A,B,C,TRUE)))

例如:这是我给出的df

Id   a  b    c    
ijk  4  3.5  12.53
xyz  12 3    10.74

我的目标:

Id   a  b    c      0    1    2    3
ijk  4  3.5  12.53  1   .93  .87  .81
xyz  12 3    10.74  1   .87  .76  .66

这是背后的数学:

第0列:始终为1

第1列:(1-NORM.DIST(a + 1,b,c,TRUE))/(1-NORM.DIST(a,b,c,TRUE))

第2栏:(1-NORM.DIST(a + 2,b,c,TRUE))/(1-NORM.DIST(a,b,c,TRUE))

第3栏:(1-NORM.DIST(a + 3,b,c,TRUE))/(1-NORM.DIST(a,b,c,TRUE))

这是我到目前为止所做的:

df1 = pd.DataFrame(df, columns=np.arange(0,4))
result = pd.concat([df, df1], axis=1, join_axes=[df.index])
result[0] = 1

我不确定在此之后该怎么做。

这是我使用正态分布函数的方法: https://support.office.com/en-us/article/normdist-function-126db625-c53e-4591-9a22-c9ff422d6d58

非常感谢!

1 个答案:

答案 0 :(得分:2)

NORM.DIST(..., TRUE)表示累积分布函数,1 - NORM.DIST(..., TRUE)表示生存函数。这些可以在scipy的统计模块下找到(参见ss.norm)。例如,

import scipy.stats as ss
ss.norm.cdf(4, 3.5, 12.53)
Out:
0.51591526057026538

对于您的情况,您可以先定义一个函数:

def normalize(a, b, c, col):
    return ss.norm.sf(a+col, b, c) / ss.norm.sf(a, b, c)

并使用apply调用该函数:

for col in range(4):
    df[col] = df.apply(lambda x: normalize(x.a, x.b, x.c, col), axis=1)

df
Out: 
    Id   a    b      c    0         1         2         3
0  ijk   4  3.5  12.53  1.0  0.934455  0.869533  0.805636
1  xyz  12  3.0  10.74  1.0  0.875050  0.760469  0.656303

这不是最有效的方法,因为它再次计算相同值的生存函数并涉及两个循环。通过将值数组传递给ss.sf

,可以省略一级循环
out = df.apply(
    lambda x: pd.Series(
        ss.norm.sf(x.a + np.arange(4), x.b, x.c) / ss.norm.sf(x.a, x.b, x.c)
        ), axis=1
)

Out: 
     0         1         2         3
0  1.0  0.934455  0.869533  0.805636
1  1.0  0.875050  0.760469  0.656303

您可以使用join将其添加到原始DataFrame中:

df.join(out)
Out: 
    Id   a    b      c    0         1         2         3
0  ijk   4  3.5  12.53  1.0  0.934455  0.869533  0.805636
1  xyz  12  3.0  10.74  1.0  0.875050  0.760469  0.656303