Вопрос об итерации ряда Панд с условными выражениями - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь создать столбец, который будет иметь нули везде, кроме случаев, когда выполняется определенное условие.

Прямо сейчас у меня есть существующая серия 0 и 1, сохраненная как объект Series. Давайте назовем эту серию A. Я создал еще одну серию того же размера, заполненную нулями, назовем эту серию B. Что я хотел бы сделать, так это когда бы я ни нажал последние 1 в последовательности 1 в серии A, тогда следующие шесть рядов серии B должны заменить 0 на 1.

Например:

Серия A

0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 ...

Должен производить серию B

0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 ...

Вот что я пробовал до сих пор:

for row in SeriesA:
    if row == 1:
        continue
    if SeriesA[row] == 1 and SeriesA[row  + 1] == 0:
        SeriesB[row]=1
        SeriesB[row+1]=1
        SeriesB[row+2]=1
        SeriesB[row+3]=1
        SeriesB[row+4]=1
        SeriesB[row+5]=1

Однако, это только генерирует Серию B, полную нулей, за исключением первых пяти рядов с стать 1. (Серия А - все нули, по крайней мере, до ряда 50)

Мне кажется, я не понимаю, как итерация работает с Pandas, поэтому любая помощь приветствуется!

РЕДАКТИРОВАТЬ: Полный (ish) код

import os
import numpy as np
import pandas as pd
df = pd.read_csv("Python_Datafile.csv", names = fields) #fields is a list with names for each column, the first column is called "Date".
df["Date"] = pd.to_datetime(df["Date"], format = "%m/%Y")
df.set_index("Date", inplace = True)

Recession = df["NBER"] # This is series A

Rin6 = Recession*0 # This is series B

gps = Recession.ne(Recession.shift(1)).where(Recession.astype(bool)).cumsum()
idx = Recession[::-1].groupby(gps).idxmax()
to_one = np.hstack(pd.date_range(start=x+pd.offsets.DateOffset(months=1), freq='M', periods=6) for x in idx)
Rin6[Rin6.index.isin(to_one)]= 1

Rin6.unique() # Returns -> array([0], dtype=int64)

1 Ответ

0 голосов
/ 17 января 2019

Вы можете создать идентификатор для последовательных групп 1 с помощью .shift + .cumsum:

gps = s.ne(s.shift(1)).where(s.astype(bool)).cumsum()

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

idx = s[::-1].groupby(gps).idxmax()

#0
#1.0     5
#2.0    18
#Name: 0, dtype: int64

Просмотреть список всех индексов с помощью np.hstack

import numpy as np

np.hstack(np.arange(x+1, x+7, 1) for x in idx)
#array([ 6,  7,  8,  9, 10, 11, 19, 20, 21, 22, 23, 24])

И установить эти индексы на 1 во второй серии:

s2[np.hstack(np.arange(x+1, x+7, 1) for x in idx)] = 1

s2.ravel()
# array([0., 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0.,..

Обновление от вашего комментария: при условии, что у вас есть Series s с индексами datetimes и еще один Series s2, который имеет те же индексы, но все значения равны 0, и у них есть MonthStart частота, вы можете продолжить в аналогичном режиме:

s = pd.Series([0,0,0,0,0,0,0,0,0,1,1]*5, index=pd.date_range('2010-01-01', freq='MS', periods=55))
s2 = s*0

gps = s.ne(s.shift(1)).where(s.astype(bool)).cumsum()
idx = s[::-1].groupby(gps).idxmax()

#1.0   2010-11-01
#2.0   2011-10-01
#3.0   2012-09-01
#4.0   2013-08-01
#5.0   2014-07-01
#dtype: datetime64[ns]

to_one = np.hstack(pd.date_range(start=x+pd.offsets.DateOffset(months=1), freq='MS', periods=6) for x in idx)

s2[s2.index.isin(to_one)]= 1
# I check .isin in case the indices extend beyond the indices in s2
...