2012-06-01 22 views
5

Właściwie mam zbiór danych o "spotkaniu". Na przykład A, B, C mają spotkanie, a następnie lista będzie miała postać [A, B, C]. W ten sposób każda lista zawiera listę członków, którzy uczestniczyli w spotkaniu. Dlatego:Python: Zliczanie częstotliwości par elementów na liście list

linia1 = (A, B, C)

linia2 = (A, C, D, E),

linia3 = (D, F, G)

..

Po prostu chciałbym policzyć liczbę, ile razy każda para członków spotyka się ze sobą. Na przykład członek A spełnia C dwa razy z linii 1 i linii 2, a członek B spełnia C raz z linii 1. Tak, chciałbym, aby wykres takiego ..

A B C D E F G... 

A . 1 2 1 ... 

B 1 . 1 0 

C 

...

Myślałem, że to będzie łatwe na pierwszy, ale jestem całkiem zdezorientowany. Proszę mi pomóc i bardzo dziękuję z góry.

+1

Czas dowiedzieć się, jak mnożyć macierze ... –

Odpowiedz

0

Jest to dość prosty problem z strukturą danych z tablicą 2D lub dyktowaniem. Tablice są bardziej wydajne, jeśli masz dużo ludzi, ale zakładam, że nie.

times_met = defaultdict(int) 
for line in lines: 
    for pair in itertools.combinations(line, 2) 
     times_met[pair] += 1 

# How many times person a meets person b is described by the following (s.t. a < b) 
print times_met[(a, b)] 

Zauważ, że jest to naprawdę nieefektywne, jeśli masz duże spotkania i bardziej wydajne algorytmy prawdopodobnie istnieją.

+1

Myślę, że dict z tuple -> int miałoby więcej sensu - tak, że 'people_met [(person1, person2)] jest spotkaniami między nimi. Wtedy nie musi to być 'defaultdict' - po prostu zapełnij go początkowo z' itertools.combinations'. – lvc

+0

@lvc A 'defaultdict (int)' ma więcej sensu semantycznie. Jeśli nowa osoba dołącza do zbioru danych, możesz zapytać, ile razy był na spotkaniu z kimkolwiek innym i uzyskać właściwą odpowiedź - 0 - zamiast "KeyError". Inicjowanie zerami jest dość un-Pythonic. Nigdy nie _edujesz 'defaultdict', ale pozwala ci to napisać lepszy kod. – agf

+0

Edycja jest dobra, ale nadal jest nieefektywna w przypadku dużych zestawów danych, ponieważ generuje się kartezjański produkt linii, zamiast samych kombinacji. Pamiętaj, że Python to baterie - istnieje już sposób na zrobienie tego. – agf

0

Wygląda na to, że powinieneś być w stanie rozwiązać ten problem, dodając matrycę. Jeśli znasz całkowitą liczbę osób (G w pytaniu), twoja odpowiedź będzie matrycą GxG. Tworzenie się matrycy GxG w kombinacjach z line1, a następnie dodawać w matrycy GxG w kombinacjach z line2 itp

7

Zamiast ręcznego sumujących częstotliwości użyć collections.counter wraz z itertools:

from collections import Counter 
from itertools import chain, combinations 

meets = Counter(chain.from_iterable(combinations(line, 2) for line in lines)) 

przypadku lines jest iterowalne z iterabli nazw.

+0

+1 za korzystanie z bibliotek Pythona. Wszystko jest gdzieś tam. >: P –

+0

+1 za rozwiązanie tak oślepiająco oczywiste, że się kopie, bo nie zauważam tego, dopóki nie odpowiesz.Gdy druga odpowiedź używa 'defaultdict (int)' i robi 'd [element] + = 1' dużo, to trochę krzyczy na' Counter'. Nie wspominając już o pytaniu "Chcę policzyć ...". – lvc

+1

Należy zauważyć, że działa to tylko wtedy, gdy elementy znajdują się w tej samej kolejności na każdej liście, np. 'Counter (chain.from_iterable (kombinacje (x, 2) dla x w [[1,2], [2,1]]))' daje 'Counter ({(1, 2): 1, (2, 1) : 1})). Jeśli chcesz policzyć każdą parę niezależnie od kolejności, najpierw zamień każdą listę w zestaw: 'Counter (chain.from_iterable (kombinacje (x, 2) dla x w [zestaw ([1,2]), zestaw ([2, 1])])) 'produkuje' Counter ({(1, 2): 2}) '. – Katrina

Powiązane problemy