mvd*_*mvd 8 python statistics numpy
我正在计算基尼系数(类似于:Python - 使用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)
Run Code Online (Sandbox Code Playgroud)
对于给定的一组数字,上面的代码计算每个百分位箱中总分布值的分数.
结果:
均匀分布应该接近"完全相等",因此洛伦兹曲线弯曲是关闭的.
War*_*ser 14
这是可以预料的.来自均匀分布的随机样本不会导致均匀值(即,彼此相对接近的值).通过一点微积分,可以证明样本的基尼系数的预期值(统计意义上)来自[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).
这是基尼系数的简单实现.它使用的基尼系数是相对平均绝对差值的一半.
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
Run Code Online (Sandbox Code Playgroud)
以下是几种形式样本的基尼系数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
Run Code Online (Sandbox Code Playgroud)
稍微快一点的实现(使用 numpy 向量化并且只计算每个差异一次):
def gini_coefficient(x):
"""Compute Gini coefficient of array of values"""
diffsum = 0
for i, xi in enumerate(x[:-1], 1):
diffsum += np.sum(np.abs(xi - x[i:]))
return diffsum / (len(x)**2 * np.mean(x))
Run Code Online (Sandbox Code Playgroud)
注意:x必须是一个numpy数组。