2015-05-04 2 views
8

В этом проблема у меня есть. Учитывая списокСумма продуктов пар в списке

xList = [9, 13, 10, 5, 3] 

Я хотел бы рассчитывать на сумму каждого элемента, умноженной на последующие элементы

sum([9*13, 9*10, 9*5 , 9*3]) + 
sum([13*10, 13*5, 13*3]) + 
sum([10*5, 10*3]) + 
sum ([5*3]) 

в этом случае ответ .

Есть ли способ сделать это, возможно, с itertools или изначально с numpy?

Ниже приведена функция, с которой я пришел. Это делает работу, но она далека от идеала, поскольку я хотел бы добавить и другие вещи.

def SumProduct(xList): 
     ''' compute the sum of the product 
     of a list 
     e.g. 
     xList = [9, 13, 10, 5, 3] 
     the result will be 
     sum([9*13, 9*10, 9*5 , 9*3]) + 
     sum([13*10, 13*5, 13*3]) + 
     sum([10*5, 10*3]) + 
     sum ([5*3]) 
     ''' 
     xSum = 0 
     for xnr, x in enumerate(xList): 
      #print xnr, x 
      xList_1 = np.array(xList[xnr+1:]) 
      #print x * xList_1 
      xSum = xSum + sum(x * xList_1) 
     return xSum 

Любая помощь приветствуется.

N.B: В случае, если вам интересно, я пытаюсь реализовать Krippendorf's alpha с панд

+0

Личные любопытство (смотрел на литературу), каковы преимущества использования этого realibility над наиболее популярных из них? – PascalVKooten

+0

Фактически, эти меры обобщены большинство других см. http://www.afhayes.com/public/cmm2007.pdf и http://www.agreestat.com/book4/ – user1043144

ответ

6

Вот один из способов:

In [14]: x = [9, 13, 10, 5, 3] 

In [15]: np.triu(np.outer(x, x), k=1).sum() 
Out[15]: 608 

, но я бы с @ user2357112 отвечают.

25
x = array([9, 13, 10, 5, 3]) 
result = (x.sum()**2 - x.dot(x))/2 

Это использует некоторые математические упрощения для работы в линейном времени и постоянном пространстве по сравнению с другими решениями, которые могут иметь квадратичную производительность.

Вот схема того, как это работает. Предположим, x = array([2, 3, 1]). Тогда если рассматривать продукты как области прямоугольников:

x is this stick: -- --- - 

x.sum()**2 is this rectangle: 
    -- --- - 
    |xx xxx x 
    |xx xxx x 

    |xx xxx x 
    |xx xxx x 
    |xx xxx x 

    |xx xxx x 

x.dot(x) is this diagonal bit: 
    -- --- - 
    |xx 
    |xx 

    | xxx 
    | xxx 
    | xxx 

    |  x 

(x.sum()**2 - x.dot(x)) is the non-diagonal parts: 
    -- --- - 
    | xxx x 
    | xxx x 

    |xx  x 
    |xx  x 
    |xx  x 

    |xx xxx 

and (x.sum()**2 - x.dot(x))/2 is the product you want: 
    -- --- - 
    | xxx x 
    | xxx x 

    |  x 
    |  x 
    |  x 

    | 
+3

Ницца, потому что линейный. – DSM

+0

@WarrenWeckesser: Упс. Исправлена. – user2357112

+2

Святой bejezes. Математика иногда очень полезна, а? – itzy

4

Похоже, что вы хотите получить все комбинации двух элементов (пар) в этом списке, вычислить произведение каждой пары, и просуммировать эти продукты :

import itertools 

xlist = [9, 13, 10, 5, 3] 
pairs = itertools.combinations(xlist, 2) 
answer = 0 
for pair in pairs: 
    answer += pair[0] * pair[1] 

Один лайнер, чтобы сделать это:

import itertools 
import operator 

sum(operator.mul(*t) for t in itertools.combinations(xlist, 2)) 
+0

спасибо. Мне не хватает iertoolools.com. Я пошел на ответ user2357112, поскольку он объясняет проблему более широко. – user1043144

1

Один подход -

xarr = np.array(xList) 

N = xarr.size 
range1 = np.arange(N) 

mask = range1[:,None] < range1 
out = ((mask*xarr)*xarr[:,None]).sum() 

Еще один -

xarr = np.array(xList) 

N = xarr.size 
range1 = np.arange(N) 

R,C = np.where(range1[:,None] < range1) 
out = (xarr[R]*xarr[C]).sum() 
7

Вы на самом деле хотите комбинации не продукт:

from itertools import combinations 

print(sum(a*b for a,b in combinations(xList,2))) 
608 

Даже создавая Numpy массив из списка питона, @user2357112 ответ вытирает пол с остальной частью нас.

In [38]: timeit sum(a*b for a,b in combinations(xlist,2)) 
10000 loops, best of 3: 
89.7 µs per loop 

In [40]: timeit sum(mul(*t) for t in itertools.combinations(xlist, 2)) 
1000 loops, best of 3: 
165 µs per loop 

In [41]: %%timeit           
x = array(arr) 
(x.sum()**2 - (x**2).sum())/2 
    ....: 
100000 loops, best of 3: 
10.9 µs per loop 

In [42]: timeit np.triu(np.outer(x, x), k=1).sum() 
10000 loops, best of 3: 
48.1 µs per loop 
In [59]: %%timeit 
....: xarr = np.array(xList) 
....: N = xarr.size 
....: range1 = np.arange(N) 
....: mask = range1[:,None] < range1 
....: out = ((mask*xarr)*xarr[:,None]).sum() 
10000 loops, best of 3: 30.4 µs per loop 

Все списки/массивы имели 50 элементов.

Кража логики от user2357112 и использовать его на нормальный список с суммой питона довольно штопать эффективным:

In [63]: timeit result = (sum(xList)**2 - sum(x ** 2 for x in xList))/2 
100000 loops, best of 3: 
4.63 µs per loop 

Но для большого массива решение NumPy по-прежнему значительно быстрее.

1

Если вы заинтересованы в этом вручную (без помощи STDLIB):

def combinations(L): 
    for i,elem in enumerate(L): 
     for e in L[i+1:]: 
      yield (elem, e) 

def main(xlist): 
    answer = 0 
    for a,b in combinations(xlist): 
     answer += a*b 
    return answer 
+1

Почему бы вам не использовать стандартную библиотеку? – chepner

+0

Несколько раз люди интересуются алгоритмом, который решает проблему, больше, чем быстрый однострочный. Именно поэтому я и предварял свой ответ «если вам интересно это сделать вручную», и добавил [более питонический ответ] (http://stackoverflow.com/a/30039432/198633) – inspectorG4dget

+1

Вопрос явно задан для решения с использованием 'itertools' или' numpy'. – chepner

Смежные вопросы