首页 > 解决方案 > 当平均值和标准值依赖于另一列值时,将高斯分布应用于特定列的所有值

问题描述

有没有办法为每个不同的列值创建一个包含每个列值的高斯/正态分布的新列?

我的意思是,如果我有 2 个具有以下结构的数据框:

>> Original Dataframe 1

      Samp     Age     Cs
1       A      51      msi
2       B      62      cin
3       C      55      msi
4       D      70      ebv
5       E      56      gs
....



>> Original DataFrame 2

   Samp   Cs  Age 
0     A  cin   51 
1     A  ebv   51
2     A   gs   51
3     A  msi   51
4     B  cin   62
5     B  ebv   62
6     B   gs   62
7     B  msi   62
8     C  cin   55
9     C  ebv   55
10    C   gs   55
11    C  msi   55
12    D  cin   70
13    D  ebv   70
14    D   gs   70
15    D  msi   70
16    E  cin   56
17    E  ebv   56
18    E   gs   56
19    E  msi   56
...

如您所见,原始数据帧 2是原始数据帧 1中CS列唯一值的行重复。

为了实现我的目标,我需要将原始数据帧 1中的均值和标准差检索到所有唯一的Cs值,因此我可以进一步将其应用于age列中的原始数据帧2以获得新的 df - Desired Datframe with新列概率

由于在这种情况下原始数据帧 1的均值和标准差是:

m = {'msi': 70.7, 'ebv': 63.2, 'cin': 66.9, 'gs': 59.3}
std = {'msi': 8.7, 'ebv': 11.2, 'cin': 10.2, 'gs': 10.2}

有没有办法输出以下数据框?

    >> Desired DataFrame

   Samp   Cs  Age  Probability
0     A  cin   51   0.01160
1     A  ebv   51   0.01968
2     A   gs   51   0.02809
3     A  msi   51   0.00353
4     B  cin   62   0.03485
5     B  ebv   62   0.03542
6     B   gs   62   0.03777
7     B  msi   62   0.00455
8     C  cin   55   0.01980
9     C  ebv   55   0.02725
10    C   gs   55   0.03579
11    C  msi   55   0.00900
12    D  cin   70   0.03735
13    D  ebv   70   0.02963
14    D   gs   70   0.02256
15    D  msi   70   0.04570
16    E  cin   56   0.02210
17    E  ebv   56   0.02897
18    E   gs   56   0.03712
19    E  msi   56   0.01100
...

到目前为止,这是我的尝试:

def get_age_cs_probs(df):
    df['Probability'] = df.groupby('Cs').Age.apply(lambda x: 
                                                         (1/(np.sqrt(2*3.14*(x.std()**2))))*(np.exp(-(((x-x.mean())**2)/(2*(x.std()**2))))))
    return df

标签: pythonpandasgroup-bygaussiannormal-distribution

解决方案


scipy.stats.zmap将根据不同的数组为您的数组提供 z 分数。

这个结果可以反馈给scipy.stats.norm.cdf(),这会将您的 z 分数转换为概率。

查看这两个函数以查看是否要指定不同的 df 或其他值而不是默认值。

我有一个答案,它会为每个“Cs”值生成一个概率列表列表,但无法找到一种干净的方法将其恢复为 df2。

df1
Out[117]: 
  Samp  Age   Cs
1    A   51  msi
2    B   62  cin
3    C   55  msi
4    D   70  ebv
5    E   56   gs

df2
Out[118]: 
   Samp   Cs  Age  Probability
0     A  cin   51      0.01160
1     A  ebv   51      0.01968
2     A   gs   51      0.02809
3     A  msi   51      0.00353
4     B  cin   62      0.03485
5     B  ebv   62      0.03542
6     B   gs   62      0.03777
7     B  msi   62      0.00455
8     C  cin   55      0.01980
9     C  ebv   55      0.02725
10    C   gs   55      0.03579
11    C  msi   55      0.00900
12    D  cin   70      0.03735
13    D  ebv   70      0.02963
14    D   gs   70      0.02256
15    D  msi   70      0.04570
16    E  cin   56      0.02210
17    E  ebv   56      0.02897
18    E   gs   56      0.03712
19    E  msi   56      0.01100

[st.norm.cdf(st.zmap(df2[df2.loc[:, 'Cs'] == x].Age, df1[df1.loc[:, 'Cs']==x].Age)) for x in df2.Cs.unique()]

Out[119]: 
[array([ 0., nan,  0.,  1.,  0.]),
 array([ 0.,  0.,  0., nan,  0.]),
 array([ 0.,  1.,  0.,  1., nan]),
 array([0.15865525, 0.9999966 , 0.84134475, 1.        , 0.9331928 ])]

这与您的预期输出不太匹配,但如果您的 df1 具有您在问题中列出的属性(即相同的 m 和 sd 值),它会匹配。


推荐阅读