Python中索引对(或多个)求和

Python中索引对(或多个)求和,python,numpy,sum,Python,Numpy,Sum,计算样本基尼系数的一种方法是使用相对平均差(RMD),它是基尼系数的2倍。RMD取决于平均差,平均差由下式给出: 因此,我需要计算示例(yi-yj)中元素对之间的每个差异。我花了相当多的时间才想出一种方法,但我想知道是否有一个函数可以为您实现这一点 起初我尝试过这个方法,但我打赌在大数据集中速度非常慢(顺便说一下,s是示例): 然后我尝试了以下不太容易理解但更快的方法: In [126]: %%timeit m = abs(s - s.reshape(len(s), 1)) MD = np.s

计算样本基尼系数的一种方法是使用相对平均差(RMD),它是基尼系数的2倍。RMD取决于平均差,平均差由下式给出:

因此,我需要计算示例
(yi-yj)
中元素对之间的每个差异。我花了相当多的时间才想出一种方法,但我想知道是否有一个函数可以为您实现这一点

起初我尝试过这个方法,但我打赌在大数据集中速度非常慢(顺便说一下,s是示例):

然后我尝试了以下不太容易理解但更快的方法:

In [126]:
%%timeit
m = abs(s - s.reshape(len(s), 1))
MD = np.sum(m)/float((len(s)**2))
G = MD / float(mean(s))
G = G/2
G
10000 loops, best of 3: 46.8 us per loop
有什么有效但易于推广的方法吗?例如,如果我想对三个指数求和怎么办

这是我使用的示例:

sample = array([5487574374,     686306,    5092789,   17264231,   41733014,
         60870152,   82204091,  227787612,  264942911,  716909668,
        679759369, 1336605253,  788028471,  331434695,  146295398,
         88673463,  224589748,  128576176,  346121028])

gini(sample)
Out[155]:
0.2692307692307692

谢谢

对于您给出的MD示例,可以通过排序利用它,您可以实现O(N*Log(N))而不是O(N^2)


通常,您必须使用动态规划或其他技术来加快计算速度,我不确定是否有“一种方法适合所有人”的解决方案。

您的问题是“我想要一种有效的方法来计算MD,因为给出了MD的公式”不是真的。MD只是一个激发我的问题的例子。这更像是“我想要一种有效且易于理解的方法来对索引求和”。@RobertSmith您能提供一个示例,以便我可以将我的代码结果与您的代码结果进行比较吗?当然。给我几秒钟,我加了一个样品。请参阅我的更新。实际上,您的fast函数比[126]中的速度慢208倍(直到计算MD为止)。很可能,一个好的解决方案需要避免任何循环。嗯,样本有多大?通过我的测试,使用fast()方法,大样本的速度要快得多。事实上,似乎整形()甚至不能在大于10^4的样本上运行,而我的在小于10^6的样本上运行不到一秒钟。对于小样本,由于函数调用等的开销,您的方法可能会更快。对于小样本,我展示的第二个代码速度更快,但对于大样本,它变得慢得让人无法忍受,这与你的代码速度相当快不同,因为你正在使用一种技巧,认识到原始和可以表示为乘法和。你知道如何扩展这个结果来考虑更多的指数吗?我会有一个想法。可能通过包含排除或二元或三元搜索。因此,如果是yi+yj-yk,则可以排序,然后对每个k进行遍历,并为最小yi和最大yj设置一个滚动区间,该区间的总和大于yk。这表明yk贡献了多少。我想对于更高的维度也是如此。此外,你可能有兴趣阅读这个答案,这是非常弱的相关性
sample = array([5487574374,     686306,    5092789,   17264231,   41733014,
         60870152,   82204091,  227787612,  264942911,  716909668,
        679759369, 1336605253,  788028471,  331434695,  146295398,
         88673463,  224589748,  128576176,  346121028])

gini(sample)
Out[155]:
0.2692307692307692
y = [2,3,2,34]

def slow(y):
    tot = 0
    for i in range(len(y)):
        for j in range(len(y)):
            if i != j:
                tot += abs(y[i] - y[j])
    return float(tot)/len(y)**2

print slow(y)

def fast(y):
    sorted_y = sorted(y)
    tot = 0
    for i, yi in enumerate(sorted_y):
        smaller = i
        bigger = len(y) - i - 1
        tot += smaller * yi - bigger * yi
    return float(2*tot)/len(y)**2

print fast(y)