python - 在 Python/numpy 中计算基尼系数

标签 python numpy statistics

我正在计算 Gini coefficient (类似于:Python - Gini coefficient calculation using Numpy)但我得到一个奇怪的结果。对于从 np.random.rand() 采样的均匀分布,基尼系数为 0.3,但我预计它会接近 0(完全相等)。这里出了什么问题?

def G(v):
    bins = np.linspace(0., 100., 11)
    total = float(np.sum(v))
    yvals = []
    for b in bins:
        bin_vals = v[v <= np.percentile(v, b)]
        bin_fraction = (np.sum(bin_vals) / total) * 100.0
        yvals.append(bin_fraction)
    # perfect equality area
    pe_area = np.trapz(bins, x=bins)
    # lorenz area
    lorenz_area = np.trapz(yvals, x=bins)
    gini_val = (pe_area - lorenz_area) / float(pe_area)
    return bins, yvals, gini_val

v = np.random.rand(500)
bins, result, gini_val = G(v)
plt.figure()
plt.subplot(2, 1, 1)
plt.plot(bins, result, label="observed")
plt.plot(bins, bins, '--', label="perfect eq.")
plt.xlabel("fraction of population")
plt.ylabel("fraction of wealth")
plt.title("GINI: %.4f" %(gini_val))
plt.legend()
plt.subplot(2, 1, 2)
plt.hist(v, bins=20)

对于给定的一组数字,上述代码计算每个百分位区间中总分布值的分数。

结果:

enter image description here

均匀分布应该接近“完全相等”,所以洛伦兹曲线弯曲是关闭的。

最佳答案

这是意料之中的。来自均匀分布的随机样本不会产生均匀值(即彼此相对接近的值)。稍加微积分,可以证明在 [0, 1] 上均匀分布的样本基尼系数的期望值(统计意义上的)是 1/3,因此得到对于给定样本,大约 1/3 的值是合理的。

使用 v = 10 + np.random.rand(500) 等样本,您将获得较低的基尼系数。这些值都接近 10.5; 相对 变化低于样本 v = np.random.rand(500)。 事实上,样本base + np.random.rand(n)的基尼系数期望值为1/(6*base + 3)。

下面是基尼系数的简单实现。它使用基尼系数是 relative mean absolute difference 的一半这一事实.

def gini(x):
    # (Warning: This is a concise implementation, but it is O(n**2)
    # in time and memory, where n = len(x).  *Don't* pass in huge
    # samples!)

    # Mean absolute difference
    mad = np.abs(np.subtract.outer(x, x)).mean()
    # Relative mean absolute difference
    rmad = mad/np.mean(x)
    # Gini coefficient
    g = 0.5 * rmad
    return g

(有关更高效的实现,请参阅 More efficient weighted Gini coefficient in Python)

这是 v = base + np.random.rand(500) 形式的几个样本的基尼系数:

In [80]: v = np.random.rand(500)

In [81]: gini(v)
Out[81]: 0.32760618249832563

In [82]: v = 1 + np.random.rand(500)

In [83]: gini(v)
Out[83]: 0.11121487509454202

In [84]: v = 10 + np.random.rand(500)

In [85]: gini(v)
Out[85]: 0.01567937753659053

In [86]: v = 100 + np.random.rand(500)

In [87]: gini(v)
Out[87]: 0.0016594595244509495

关于python - 在 Python/numpy 中计算基尼系数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39512260/

相关文章:

c++ - C、C++ 或 Fortran 中的多元正态 cdf

algorithm - 网络爬虫 : Assigning a score to a URL (using its words composing it) given statistics of words previously crawled

python - 如何使用 pandas/numpy/python 数学库计算平均绝对误差 (MAE) 和平均有符号误差 (MSE)?

python - lxml 返回 DTD 属性的空列表

python - 你如何在 Numpy 中找到 IQR?

python - pyAudio 在调用 start_stream 之前开始流式传输

python - dtype ('float64' 的值太大)

python - 相当于 tensorflow 中的 np.add.at

python - 在 Python 中对字符串列表进行排序

python - 在 match.group 上重新订阅