Фрейм данных: сравните значение столбца и одну строку ниже - PullRequest
1 голос
/ 26 октября 2019

У меня есть фрейм данных с указаниями:

        Direction: 
2/01/19 None
1/31/19 Upward
1/30/19 None
1/29/19 None
1/28/19 Downward
1/27/19 None
1/26/19 None
1/25/19 Upward

Я хочу создать столбец «Momentum» на основе следующих условий (начиная с 25.01.19):
1. ЕслиНаправление для соответствующей даты - «Вверх», затем установите значение «Вверх»
2. Если в строке ниже Momentum указано «Вверх», установите «Вверх»
3. Если Направление длясоответствующая дата - «Вниз», затем установите «Нет»
4. В противном случае установите «Нет»

Сказано иначе, как только вы достигнете статуса «Вверх», оно должно оставаться таким же. пока вы не нажмете «Вниз»

Результат должен выглядеть следующим образом:

        Direction:  Momentum:
2/01/19 None        Upward
1/31/19 Upward      Upward
1/30/19 None        None
1/29/19 None        None
1/28/19 Downward    None
1/27/19 None        Upward
1/26/19 None        Upward
1/25/19 Upward      Upward

Есть ли способ сделать это без использования цикла?

Ответы [ 2 ]

2 голосов
/ 26 октября 2019

РЕДАКТИРОВАННЫЙ ответ по новым данным сначала заполняет значения None, а затем заменяет Downward на None s:

#first replace strings Nones to None type
df['Direction:'] = df['Direction:'].mask(df['Direction:'] == 'None', None)
df['Momentum:'] = df['Direction:'].bfill().mask(lambda x: x == 'Downward', None)

Или:

s = df['Direction:'].bfill()
df['Momentum:'] = s.mask(s == 'Downward', None)

print (df)
        Direction:  Momentum:
2/01/19       None     Upward
1/31/19     Upward     Upward
1/30/19       None       None
1/29/19       None       None
1/28/19   Downward       None
1/27/19       None     Upward
1/26/19       None     Upward
1/25/19     Upward     Upward

Старый ответ:

Использование numpy.where с логической цепочкой для сравнения смещенных значений, а также оригинала на | для побитового ИЛИ:

mask = df['Direction:'].eq('Upward') | df['Direction:'].shift(-1).eq('Upward')
df['Momentum:'] = np.where(mask, 'Upward', None)
print (df)
        Direction: Momentum:
1/31/19       None    Upward
1/30/19     Upward    Upward
1/29/19       None      None
1/28/19       None      None
1/27/19   Downward      None
1/26/19       None    Upward
1/25/19     Upward    Upward
2 голосов
/ 26 октября 2019

Вот один из способов. Я постараюсь улучшить его после кофе ...

df['Momentum:'] = None  # Base case.
df.loc[df['Direction:'].eq('Upward'), 'Momentum:'] = 'Upward'
df.loc[df['Direction:'].eq('Downward'), 'Momentum:'] = 1  # Temporary value.
df.loc[:, 'Momentum:'] = df['Momentum:'].bfill()
df.loc[df['Momentum:'].eq(1), 'Momentum:'] = None  # Set temporary value back to None.
>>> df
        Direction: Momentum:
2/01/19       None    Upward
1/31/19     Upward    Upward
1/30/19       None      None
1/29/19       None      None
1/28/19   Downward      None
1/27/19       None    Upward
1/26/19       None    Upward
1/25/19     Upward    Upward
...