Python数据框架中的置信区间

12
我正在尝试计算一个大数据集中"Force"列的均值和置信区间(95%),我需要通过使用groupby函数对不同的"Classes"进行分组来获得结果。当我计算均值并将其放入新数据框中时,所有行都会给出NaN值。我不确定我是否正确操作了。有没有更简单的方法可以做到这一点?这是样本数据框:
df=pd.DataFrame({ 'Class': ['A1','A1','A1','A2','A3','A3'], 
                  'Force': [50,150,100,120,140,160] },
                   columns=['Class', 'Force'])

为了计算置信区间,我首先计算了均值。这是我使用的方法:

F1_Mean = df.groupby(['Class'])['Force'].mean()

这使得所有行的值都变成了NaN


你可以使用Bootstrap:https://dev59.com/questions/_6Lia4cB1Zd3GeqPh1to#66008548 - Marco Cerliani
5个回答

32

2021年10月25日更新:@a-donda 指出,95%的基础应该是平均值的1.96倍标准差。

import pandas as pd
import numpy as np
import math

df=pd.DataFrame({'Class': ['A1','A1','A1','A2','A3','A3'], 
                 'Force': [50,150,100,120,140,160] },
                 columns=['Class', 'Force'])
print(df)
print('-'*30)

stats = df.groupby(['Class'])['Force'].agg(['mean', 'count', 'std'])
print(stats)
print('-'*30)

ci95_hi = []
ci95_lo = []

for i in stats.index:
    m, c, s = stats.loc[i]
    ci95_hi.append(m + 1.96*s/math.sqrt(c))
    ci95_lo.append(m - 1.96*s/math.sqrt(c))

stats['ci95_hi'] = ci95_hi
stats['ci95_lo'] = ci95_lo
print(stats)

输出为

  Class  Force
0    A1     50
1    A1    150
2    A1    100
3    A2    120
4    A3    140
5    A3    160
------------------------------
       mean  count        std
Class                        
A1      100      3  50.000000
A2      120      1        NaN
A3      150      2  14.142136
------------------------------
       mean  count        std     ci95_hi     ci95_lo
Class                                                
A1      100      3  50.000000  156.580326   43.419674
A2      120      1        NaN         NaN         NaN
A3      150      2  14.142136  169.600000  130.400000

2
这是一个非常出色的答案。我希望我能够奖励它。返回一个包含所有统计数据的 df 是一个非常好的做法。干得好。 - autonopy
这是我的补充:为了使其返回格式化的字符串列,请添加以下内容: stats['95p_ci'] = "(" + stats['ci95_lo'].round(1).astype(str) + ', ' + stats['ci95_hi'].round(1).astype(str) + ')' - autonopy
2
95%置信区间的正确乘数是1.96,而不是1.95。此外,请注意,这是基于正态分布对二项分布的近似,并且仅适用于大样本。 - A. Donda
@A.Donda,你是正确的。让我更新一下。 - yoonghm

6

你可以利用“sem”(平均标准误差)来简化 @yoonghm 的解决方案。

import pandas as pd
import numpy as np
import math

df=pd.DataFrame({'Class': ['A1','A1','A1','A2','A3','A3'], 
                 'Force': [50,150,100,120,140,160] },
                 columns=['Class', 'Force'])
print(df)
print('-'*30)

stats = df.groupby(['Class'])['Force'].agg(['mean', 'sem'])
print(stats)
print('-'*30)


stats['ci95_hi'] = stats['mean'] + 1.96* stats['sem']
stats['ci95_lo'] = stats['mean'] - 1.96* stats['sem']
print(stats)

3
不是故意想让你烦恼,但1.96 * sd公式过于简化了,对于较小的样本会导致错误的结论。建议使用t分布代替:
import pandas as pd
import scipy.stats as stats

df=pd.DataFrame({'Class': ['A1','A1','A1','A2','A3','A3'],
                 'Force': [50,150,100,120,140,160] },
                 columns=['Class', 'Force'])
print(df)
grouped = df.groupby(['Class'])['Force'].agg(['mean', 'count', 'std'])

# Calculate the t-value for a 95% confidence interval
t_value = stats.t.ppf(0.975, grouped['count'] - 1)  # 0.975 corresponds to (1 - alpha/2)
# Calculate the margin of error
me = t_value * grouped['std'] / (grouped['count'] ** 0.5)
# Calculate the lower and upper bounds of the confidence interval   
grouped['ci_low'] = grouped['mean'] - me 
grouped['ci_high'] = grouped['mean'] + me 
print(grouped)

输出 =

  Class  Force
0    A1     50
1    A1    150
2    A1    100
3    A2    120
4    A3    140
5    A3    160
        mean  count        std     ci_low     ci_high
Class                                                
A1     100.0      3  50.000000 -24.206886  224.206886
A2     120.0      1        NaN        NaN         NaN
A3     150.0      2  14.142136  22.937953  277.062047


(感谢ChatGPT 3.5的协助)

0

如评论中所述,我无法复制您的错误,但您可以尝试检查您的数字是否存储为数字而不是字符串。使用df.info()并确保相关列为float或int:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 2 columns):
Class    6 non-null object   # <--- non-number column
Force    6 non-null int64    # <--- number (int) column
dtypes: int64(1), object(1)
memory usage: 176.0+ bytes

0
我认为pd.Series.quantile方法可以用来返回类似这样的置信区间:
confidence_intervals = df.groupby('Class').quantile(q=[0.025, 0.975])
print(confidence_intervals)

输出:

             Force
Class             
A1    0.025   52.5
      0.975  147.5
A2    0.025  120.0
      0.975  120.0
A3    0.025  140.5
      0.975  159.5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接