2011-02-08 18 views
6

Edycja tytułu: poprawiono pisownię i dodano "dla pythona".Grupowanie serii w Pythonie

Czy istnieje lepszy lub bardziej standardowy sposób robienia tego, co opisuję? Chcę wejście tak:

[1, 1, 1, 0, 2, 2, 0, 2, 2, 0, 0, 3, 3, 0, 1, 1, 1, 1, 1, 2, 2, 2]

zostać przekształcone do tego:

[0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 2, 0]

lub, jeszcze lepiej, coś takiego (opisujący podobny wynik inaczej, ale teraz nie ogranicza się do liczby całkowite):

etykiety: [1, 2, 3, 1, 2]

pozycje (gdzie 1 zidentyfikowane pierwszy occupiable pozycję, jak na moje matplotlib działki): [2, 7, 12.5, 17, 21]

Dane wejściowe to dane kategoryczne że sklasyfikowane działkę - na zdjęciu poniżej, pogrupowane Działki dzielą kategoryczne funkcji, które chciałbym oznaczać tylko raz dla grupy. Będę używał 2 osi dla dwóch różnych zmiennych, ale myślę, że to jest poza tym punktem na razie.

Uwaga: Obraz ten nie odzwierciedla zestawu danych przykładowych - wystarczy, że poradzi sobie z ideą grupowania kategorii. Grupa a powinna być oznaczona jako x = 5, ponieważ między pierwszą a drugą grupą danych w pionie jest spacja, a 0 to linia po prawej stronie.

Image demonstrating placement of tick marks in the center of a category of data

Oto co mam:

data = [1, 1, 1, 2, 2, 2, 2, 2, 3, 4, 3, 2, 2, 1, 1, 1, 1] 
last = None 
runs = [] 
labels = [] 
run = 1 
for x in data: 
    if x in (last, 0): 
     run += 1 
    else: 
     runs.append(run) 
     run = 1 
     labels.append(x) 
    last = x 
runs.append(run) 
runs.pop(0) 
labels.append(x) 
tick_positions = [0] 
last_run = 1 
for run in runs: 
    tick_positions.append(run/2.0+last_run/2.0+tick_positions[-1]) 
    last_run = run 
tick_positions.pop(0) 
print tick_positions 

Odpowiedz

8

Aby uzyskać etykiety można użyć itertools groupby:

>>> import itertools 
>>> numbers = [1, 1, 1, 0, 2, 2, 0, 2, 2, 0, 0, 3, 3, 0, 1, 1, 1, 1, 1, 2, 2, 2] 
>>> list(k for k, g in itertools.groupby(numbers)) 
[1, 0, 2, 0, 2, 0, 3, 0, 1, 2] 

oraz usunięcie zer można użyć ze zrozumieniem :

>>> list(k for k, g in itertools.groupby(x for x in numbers if x != 0)) 
[1, 2, 3, 1, 2] 

Jeśli chcesz uzyskać te pozycje, będziesz musiał powtórzyć listę samodzielnie, tak jak już to robisz. groupby nie śledzi tego dla Ciebie.

+1

Dokładnie to, co wyobrażałem sobie gdzieś istniało - przypomina mi się, że "gdzieś" prawie zawsze jest itertools. Dzięki. – Thomas

+2

1) Również pozycje są ważne 2) Że '0' między dwiema sekwencjami' 2' również powinno być zignorowane. Domyślam się, że nie ma opcji, ale w jakiś sposób generowania tej pośredniej tablicy, wystarczy zgrupowanie wszystkich powtarzających się wartości nie wystarczy. – rsenna

+0

rsenna ma rację, to nie działa dla wszystkiego, czego potrzebuję, ale spodziewam się, że jest to rozwiązanie w puszkach, ponieważ zamierzam je znaleźć - wygląda na to, że dokładna odpowiedź na moje pytanie byłaby "nie", ale to jest nudne. – Thomas