Pandas 创建法线距离系列

Pandas Creating Normal Dist series

我正在尝试将 excel "normal distribution" 公式转换为 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

非常感谢!

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