python计算基尼系数_PHP算法

2022-09-28 10:46:23 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君

基尼系数是指国际上通用的、用以衡量一个国家或地区居民收入差距的常用指标。是20世纪初意大利经济学家基尼,于1922年提出的定量测定收入分配差异程度的指标。它是根据洛伦兹曲线找出了判断分配平等程度的指标(如下图)。

设实际收入分配曲线和收入分配绝对平等曲线之间的面积为A,实际收入分配曲线右下方的面积为B。并以A除以A B的商表示不平等程度。这个数值被称为基尼系数或称洛伦茨系数。如果A为零,基尼系数为零,表示收入分配完全平等;如果B为零则系数为1,收入分配绝对不平等。该系数可在零和1之间取任何值。收入分配越是趋向平等,洛伦茨曲线的弧度越小,基尼系数也越小,反之,收入分配越是趋向不平等,洛伦茨曲线的弧度越大,那么基尼系数也越大。如果个人所得税能使收入均等化,那么,基尼系数即会变小。

基尼系数最大为“1”,最小等于“0”。基尼系数越接近0表明收入分配越是趋向平等。国际惯例把0.2以下视为收入绝对平均,0.2-0.3视为收入比较平均;0.3-0.4视为收入相对合理;0.4-0.5视为收入差距较大,当基尼系数达到0.5以上时,则表示收入悬殊。

基尼系数的计算公式推导

A B的面积=1/2*100%*100%=1/2

其次计算B的面积的话,由于洛伦茨曲线是一条不规则的曲线,无法直接计算B的面积,因此采用近似梯形的面积来代替。

假定全部人口平均分为n组,已累积到第i组人口总收入占全部人口总收入的比重Wi为下底,已累计的第i-1组人口总收入收入占全部人口总收入的比重Wi-1为上底,以每组人口占全部人口的比例即1/n为高,计算一个个小梯形的面积,并加总,即得到近似B的面积:

因此基尼系数的计算公式为:

例子:用户补贴从小到大排列,均分n=100份,前1%用户的总补贴,(0%-2.0%) 用户的总补贴,。。。 0%-100%用户的总补贴为:[1,1 2,1 2 3,…,1 2 … 100]

1、全部用户总补贴累计为1 2 3 … 100=5050

2、每一组已累计补贴占用比重分别为[1/5050,(1 2)/5050,(1 2 3)/5050,…,(1 2 … 100)/5050],假设分别对应到y轴上的高为a,b,c,d, … ,ma,max,a=1/5050,……,max=(1 2 … 100)/5050

3、B的面积就是计算每一个小梯形面积之后进行累加,梯形的高均为1/n,面积累加就是1/n*[(0 a)/2 (a b)/2 (b c)/2 ……(ma max)/2] = 1/n*[(b c … ma max) – max/2]

第一个小梯形实际是个三角形,面积是1/n*[(0 a)/2],注意最后一个梯形的下底只加了一次max/2,最后汇总完之后会减去一个max/2

B的面积=[(1) (1 2) (1 2 3) …… (1 2 3 …… 100) – (1 2 3 …… 100)/2 ]/5050/100

4、基尼系数G=1-2B=1-2[(1) (1 2) (1 2 3) …… (1 2 3 …… 100) – (1 2 3 …… 100)/2 ]/5050/100

代码实现

Python实现

代码语言:javascript复制
import numpy as np
n = 100
wealths = [i for i in range(1,101)] #[1,2,3…100]
cum_wealths = np.cumsum(sorted(np.append(wealths, 0))) #加上0,再排序,再计算cumsum
max = cum_wealths[-1]  # 取最后一个,也就是原数组的和
print(np.sum(cum_wealths)) #np.sum(cum_wealths) 是将所有元素求和
print(1-2*((np.float(np.sum(cum_wealths))-max/2)/max/n) #代入基尼系数公式

其他的Python实现方式可参考: http://www.pianshen.com/article/85166463/

SQL实现

代码语言:javascript复制
with userdaystat as (
    select COALESCE(total_cash,0) total_cash
        ,ntile(100) over(order by COALESCE(total_cash,0) asc ) as bucket_id --按补贴升序的顺序平均分成100份 
    --  Ntile:是一个窗口函数,它把有序的数据集合 平均分配 到 指定的数量(num)个桶中, 将桶号分配给每一行。如果不能平均分配,则优先分配较小编号的桶,并且各个桶中能放的行数最多相差1。
    from sync_mongo_box.extract_source__userdaystat
    where pt = '2019-09-01'
) , subsidy_rank as (
    select bucket_id
        ,avg(total_cash) total_cash_avg --按照分组分别计算每一组补贴的平均值
    from userdaystat
    group by bucket_id
)
select 1-(sum(total_cash_avg * (101-bucket_id))-sum(total_cash_avg)/2)/sum(total_cash_avg)/50  --代入基尼系数公式
from subsidy_rank


--最后结果公式约分后
 
with userdaystat as (
    select COALESCE(total_cash,0) total_cash
        ,ntile(100) over(order by COALESCE(total_cash,0) asc ) as bucket_id --按补贴升序的顺序平均分成100份 
    --  Ntile:是一个窗口函数,它把有序的数据集合 平均分配 到 指定的数量(num)个桶中, 将桶号分配给每一行。如果不能平均分配,则优先分配较小编号的桶,并且各个桶中能放的行数最多相差1。
    from sync_mongo_box.extract_source__userdaystat
    where pt = '2019-09-01'
)
select 1-(sum(total_cash * (101-bucket_id))-sum(total_cash)/2)/sum(total_cash)/50
from userdaystat;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/184862.html原文链接:https://javaforall.cn

0 人点赞