2015-10-13 1 views
0

я работаю с pd.Series, который выглядит следующим образом:панды Лейбл Последовательность 1 в 0-1 значной серии

2013-01-02  NaN 
2013-01-03  NaN 
2013-01-04  NaN 
2013-01-07 1.000000 
2013-01-08 1.000000 
2013-01-09 1.000000 
2013-01-10 1.000000 
2013-01-11 1.000000 
2013-01-14 1.000000 
2013-01-15 1.000000 
2013-01-16 1.000000 
2013-01-24 1.000000 
2013-01-25 1.000000 
2013-01-31 1.000000 
2013-02-01   0 
2013-02-04   0 
2013-02-05   0 
2013-02-11 -1.000000 
2013-02-12 -1.000000 
2013-02-13 -1.000000 
2013-02-14   0 
2013-02-15   0 
2013-02-18   0 

То, что я хотел бы сделать, это получить серии, как это:

2013-01-02  NaN 
2013-01-03  NaN 
2013-01-04  NaN 
2013-01-07 1.000000 
2013-01-08 1.000000 
2013-01-09 1.000000 
2013-01-10 1.000000 
2013-01-11 1.000000 
2013-01-14 1.000000 
2013-01-15 1.000000 
2013-01-16 1.000000 
2013-01-24 1.000000 
2013-01-25 1.000000 
2013-01-31 1.000000 
2013-02-01   0 
2013-02-04   0 
2013-02-05   0 
2013-02-11 2.000000 
2013-02-12 2.000000 
2013-02-13 2.000000 
2013-02-14   0 
2013-02-15   0 
2013-02-18   0 

Это то, что я хотел бы подсчитать последовательности значений non-нули и не NaN. Я не могу понять, как это сделать.

ответ

1

Это немного сложно, но использует шаблоны, которые часто возникают при работе с группами непрерывного кластера. (На самом деле нам нужно улучшить поддержку смежных groupbys, но это потребует изменения базовых структур данных, поэтому никто не удосужился к нему еще.)

Один из способов:


Ниже приводится объяснение. (Для того, чтобы сохранить этот короткий, я подавляя много повторения.)

Во-первых, мы хотим, чтобы выбрать те ценности, которые мы собираемся быть маркировка:

>>> cl = (ser.notnull() & (ser != 0)) 
>>> cl 
2013-01-02 False 
2013-01-03 False 
2013-01-04 False 
2013-01-07  True 
... 
2013-01-31  True 
2013-02-01 False 
2013-02-04 False 
2013-02-05 False 
2013-02-11  True 
2013-02-12  True 
2013-02-13  True 
2013-02-14 False 
2013-02-15 False 
2013-02-18 False 
dtype: bool 

Теперь мы находим начало каждого кластера путем сравнения его с сдвинутой версией себя:

>>> cl != cl.shift() 
2013-01-02  True 
2013-01-03 False 
2013-01-04 False 
2013-01-07  True 
2013-01-08 False 
2013-01-09 False 
... 
2013-01-31 False 
2013-02-01  True 
2013-02-04 False 
2013-02-05 False 
2013-02-11  True 
2013-02-12 False 
2013-02-13 False 
2013-02-14  True 
2013-02-15 False 
2013-02-18 False 
dtype: bool 

Но мы хотим только начинается, когда кластер мы хотим начинается номер:

>>> (cl != cl.shift()) & cl 
2013-01-02 False 
2013-01-03 False 
2013-01-04 False 
2013-01-07  True 
2013-01-08 False 
... 
2013-02-05 False 
2013-02-11  True 
2013-02-12 False 
2013-02-13 False 
2013-02-14 False 
2013-02-15 False 
2013-02-18 False 
dtype: bool 

Когда мы берем накопленную сумму из них, так как Истинного == 1 и Ложный == 0, мы получаем новый номер для каждой группы:

>>> ((cl != cl.shift()) & cl).cumsum() 
2013-01-02 0 
2013-01-03 0 
2013-01-04 0 
2013-01-07 1 
2013-01-08 1 
... 
2013-02-05 1 
2013-02-11 2 
2013-02-12 2 
2013-02-13 2 
2013-02-14 2 
2013-02-15 2 
2013-02-18 2 
dtype: int64 

Но мы не хотим, чтобы пронумеровать группы, где они не являются частью кластера:

>>> ((cl != cl.shift()) & cl).cumsum() * cl 
2013-01-02 0 
2013-01-03 0 
2013-01-04 0 
2013-01-07 1 
2013-01-08 1 
... 
2013-01-31 1 
2013-02-01 0 
2013-02-04 0 
2013-02-05 0 
2013-02-11 2 
2013-02-12 2 
2013-02-13 2 
2013-02-14 0 
2013-02-15 0 
2013-02-18 0 
dtype: int64 

И, наконец, мы хотим, чтобы оригинал NaNs быть сохранены:

>>> ((cl != cl.shift()) & cl).cumsum() * cl + (ser * 0) 
2013-01-02 NaN 
2013-01-03 NaN 
2013-01-04 NaN 
2013-01-07  1 
2013-01-08  1 
... 
2013-01-31  1 
2013-02-01  0 
2013-02-04  0 
2013-02-05  0 
2013-02-11  2 
2013-02-12  2 
2013-02-13  2 
2013-02-14  0 
2013-02-15  0 
2013-02-18  0 
dtype: float64 
+0

Wooo очень впечатляет. Спасибо за вашу помощь! – marino89

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