我正在尝试将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
非常感谢!
答案 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