statistics - Julia 中的基尼系数 : Efficient and Accurate Code

标签 statistics distribution julia inequality

我正在尝试在 Julia 中实现以下公式来计算 Gini coefficient工资分配:

enter image description here

哪里enter image description here

这是我为此使用的代码的简化版本:

# Takes a array where first column is value of wages
# (y_i in formula), and second column is probability
# of wage value (f(y_i) in formula).
function gini(wagedistarray)
    # First calculate S values in formula
    for i in 1:length(wagedistarray[:,1])
        for j in 1:i
            Swages[i]+=wagedistarray[j,2]*wagedistarray[j,1]
        end
    end

    # Now calculate value to subtract from 1 in gini formula
    Gwages = Swages[1]*wagedistarray[1,2]
    for i in 2:length(Swages)
        Gwages += wagedistarray[i,2]*(Swages[i]+Swages[i-1])
    end

    # Final step of gini calculation
    return giniwages=1-(Gwages/Swages[length(Swages)])          
end

wagedistarray=zeros(10000,2)                                 
Swages=zeros(length(wagedistarray[:,1]))                    

for i in 1:length(wagedistarray[:,1])
   wagedistarray[i,1]=1
   wagedistarray[i,2]=1/10000
end


@time result=gini(wagedistarray)

它给出的值接近于零,这是您对完全平等的工资分配的期望。然而,它需要相当长的时间:6.796 秒。

有什么改进的想法吗?

最佳答案

尝试这个:

function gini(wagedistarray)
    nrows = size(wagedistarray,1)
    Swages = zeros(nrows)
    for i in 1:nrows
        for j in 1:i
            Swages[i] += wagedistarray[j,2]*wagedistarray[j,1]
        end
    end

    Gwages=Swages[1]*wagedistarray[1,2]
    for i in 2:nrows
        Gwages+=wagedistarray[i,2]*(Swages[i]+Swages[i-1])
    end

    return 1-(Gwages/Swages[length(Swages)])

end

wagedistarray=zeros(10000,2)
for i in 1:size(wagedistarray,1)
   wagedistarray[i,1]=1
   wagedistarray[i,2]=1/10000
end

@time result=gini(wagedistarray)
  • 之前的时间:5.913907256 seconds (4000481676 bytes allocated, 25.37% gc time)
  • 之后的时间:0.134799301 seconds (507260 bytes allocated)
  • 时间(第二次运行):elapsed time: 0.123665107 seconds (80112 bytes allocated)

  • 主要问题是Swages是一个全局变量(不在函数中),这不是一个好的编码习惯,但更重要的是一个 performance killer .我注意到的另一件事是 length(wagedistarray[:,1]) ,它制作该列的副本,然后询问其长度 - 这会产生一些额外的“垃圾”。第二次运行速度更快,因为第一次运行该函数时有一些编译时间。

    您可以使用 @inbounds 提高性能, IE。
    function gini(wagedistarray)
        nrows = size(wagedistarray,1)
        Swages = zeros(nrows)
        @inbounds for i in 1:nrows
            for j in 1:i
                Swages[i] += wagedistarray[j,2]*wagedistarray[j,1]
            end
        end
    
        Gwages=Swages[1]*wagedistarray[1,2]
        @inbounds for i in 2:nrows
            Gwages+=wagedistarray[i,2]*(Swages[i]+Swages[i-1])
        end
    
        return 1-(Gwages/Swages[length(Swages)])
    end
    

    这给了我 elapsed time: 0.042070662 seconds (80112 bytes allocated)
    最后,看看这个版本,它实际上比所有版本都快,也是我认为最准确的:
    function gini2(wagedistarray)
        Swages = cumsum(wagedistarray[:,1].*wagedistarray[:,2])
        Gwages = Swages[1]*wagedistarray[1,2] +
                    sum(wagedistarray[2:end,2] .* 
                            (Swages[2:end]+Swages[1:end-1]))
        return 1 - Gwages/Swages[end]
    end
    

    其中有elapsed time: 0.00041119 seconds (721664 bytes allocated) .主要的好处是从 O(n^2) double for 循环变为 O(n) cumsum .

    关于statistics - Julia 中的基尼系数 : Efficient and Accurate Code,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31321810/

    相关文章:

    statistics - 为什么 Julia Distribution 包不能使用整数?

    java - 即时计算百分位数

    github - 是否可以比较 Github 用户?具体是他们的贡献?

    python - 嵌套while循环分布计算

    concurrency - Julia 语言 - @async tasks::Current-Directory 中的状态

    memory - Julia:高效的内存分配

    duplicates - Julia:从数组中检测并删除重复的行?

    r - lda.collapsed.gibbs.sampler 模型和热门词排名

    数据点的随机曲线分布

    python - 如何在 Pandas 数据框中创建倾斜列?