如何从频率分布表中获取均值和标准差

5
我有一个元组列表 [(val1, freq1), (val2, freq2) .... (valn, freqn)]。我需要计算这些数据的中心趋势度量(平均数,中位数)和偏差度量(方差,标准差)。另外,我还想为这些值绘制箱线图。
我发现numpy数组有直接从值列表获取均值/中位数和标准差(或方差)的方法。
numpy(或其他众所周知的库)是否有直接操作这种频率分布表格的方法?
另外:编程上最好的扩展上述元组列表到一个列表的方法是什么?(例如,如果频率分布是[(1,3) , (50,2)],则获得一个列表[1,1,1,50,50]以使用np.mean([1,1,1,50,50])的最佳方法是什么?)
我在这里看到一个自定义函数,但如果可能的话,我想使用标准实现。

@ayhan 我已将你的解决方案归因于描述...并澄清了我正在寻找什么。你能删除重复的标签吗? - jithu83
3个回答

13

首先,我会像@user8153一样将那个凌乱的列表转换成两个numpy数组:

val, freq = np.array(list_tuples).T

然后,您可以重构数组(使用np.repeat防止循环):
data = np.repeat(val, freq)

使用numpy统计函数处理你的data数组。


如果这导致内存错误(或者你想尽可能地提高性能),你还可以使用一些专门构建的函数:

def mean_(val, freq):
    return np.average(val, weights = freq)

def median_(val, freq):
    ord = np.argsort(val)
    cdf = np.cumsum(freq[ord])
    return val[ord][np.searchsorted(cdf, cdf[-1] // 2)]

def mode_(val, freq): #in the strictest sense, assuming unique mode
    return val[np.argmax(freq)]

def var_(val, freq):
    avg = mean_(val, freq)
    dev = freq * (val - avg) ** 2
    return dev.sum() / (freq.sum() - 1)

def std_(val, freq):
    return np.sqrt(var_(val, freq))

在函数“var_”中的“return dev.sum() / (freq.sum() - 1)”处出现错误,“Float64Index”对象没有属性“sum”。 - ppau2004
@ppau2004 我相信 pandas 库已经有更好的实现版本了。如果你找不到,可能需要提出一个问题来询问(虽然我不是 pandas 专家,但这里有很多人可以帮助你)。 - Daniel F
实际上,@AditjaRajgor在下面给出了一个pandas答案。 - Daniel F

4
import pandas as pd
import math
import numpy as np

频率分布数据

    class   freq
0   60-65   3
1   65-70   150
2   70-75   335
3   75-80   135
4   80-85   4

创建班级的中间点列。
df[['Upper','Lower']]=df['class'].str.split('-',expand=True)
df['Xi']=(df['Upper'].astype(float)+df['Lower'].astype(float))/2
df.drop(['Upper','Lower'],axis=1,inplace=True)

因此

    class   freq  Xi
0   60-65   3     62.5
1   65-70   150   67.5
2   70-75   335   72.5
3   75-80   135   77.5
4   80-85   4     82.5

Mean

mean = np.average(df['Xi'], weights=df['freq'])
mean
72.396331738437

标准差

std = np.sqrt(np.average((df['Xi']-mean)**2,weights=df['freq']))
std
3.5311919641103877

谢谢@Adita Rajgor。我没能成功执行中位数操作。你能指点我正确的方向吗?[-> 这里] - undefined

3
  • To convert the (value, frequency) list to a list of values:

    freqdist =  [(1,3), (50,2)]
    sum(([val,]*freq for val, freq in freqdist), []) 
    

    gives

    [1, 1, 1, 50, 50]
    
  • To compute the mean you can avoid the building of the list of values by using np.average which takes a weights argument:

    vals, freqs = np.array(freqdist).T
    np.average(vals, weights = freqs)
    

    gives 20.6 as you would expect. I don't think this works for the mean, variance, or standard deviation, though.


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