Это немного сложно, но использует шаблоны, которые часто возникают при работе с группами непрерывного кластера. (На самом деле нам нужно улучшить поддержку смежных 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
Wooo очень впечатляет. Спасибо за вашу помощь! – marino89