2011-02-08 5 views
6

Редактирование заголовка: добавлена ​​капитализация и добавлен параметр «для python».Группировка серии в Python

Есть ли лучший или более стандартный способ делать то, что я описываю? Я хочу, чтобы вход, как это:

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

быть преобразован к этому:

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

или, еще лучше, что-то вроде этого (описание аналогичного вывода по-разному, но теперь не ограничивается целые числа):

этикеты: [1, 2, 3, 1, 2]

позиция (где 1 идентифицированная первую occupiable позиция, согласно моему Matplotlib участка): [2, 7, 12.5, 17, 21]

Входные данные категорические данные, классифицируемых сюжету - на рисунке, сгруппированные участки разделяют категорическую особенность, которую я хотел бы для маркировки только один раз для группы. Я буду использовать 2 оси для двух разных переменных, но я думаю, что это не так.

Примечание: Данное изображение не отражает набор данных образца - это просто, чтобы понять идею группировки категорий. Группа a должна быть помечена в x = 5, так как между первыми двумя и вторыми вертикальными группами данных пустое пространство, а 0 - строка с правой стороны.

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

Вот что я получил:

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 

ответ

8

Чтобы получить метки можно использовать 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] 

И удалить нули вы можете использовать понимание :

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

Если вы хотите получить позиции тоже, вам придется перебирать список самостоятельно, как вы уже делаете. groupby не отслеживает это для вас.

+1

Это именно то, что я представлял где-то где-то - мне напомнили, что «где-то» почти всегда itertools. Благодарю. – Thomas

+2

1) Позиции также важны. 2) Следует также игнорировать '0' между двумя последовательностями' 2'. Я думаю, что нет никакого варианта, но каким-то образом генерирует этот промежуточный массив, просто группировать все повторяющиеся значения недостаточно. – rsenna

+0

rsenna прав, это не работает для всего, что мне нужно, но я ожидаю, что это законченное решение, как я собираюсь найти - похоже, что точный ответ на мой вопрос был бы «нет», но это скучно. – Thomas

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