Сложная условная сумма - PullRequest
       8

Сложная условная сумма

2 голосов
/ 25 апреля 2019

Я хочу задать вопрос о пандах, думаю, было бы неплохо объяснить вопрос на небольшом примере.

У меня есть

 Group     Price
 0         102
 0         103
 0         105
 1         106
 0         105
 0         106
 1         103
 0         105

хочу

 Group     Price   Impact
 0         102     
 0         103
 0         105
 1         106     -5    (103 - 108)
 0         104
 0         108
 1         101     -3    (104-107)
 0         107

Итак, я хочу найти разницу между предыдущими (t-2) и последующими (t + 2) вторыми строками, если значение моей группы равно 1 (t). Например, в первом случае значение воздействия равно -5. Это просто потому, что значение моей группы равно 1 в 4-й строке (t), а код находит разницу между второй (t-2) и шестой (t + 2) строками. Я могу это с помощью следующего кода:

 i = Data.loc[Data.Group.eq(1)].index.tolist()
 j = [(i-2,i+2) for i_ in i ]
 Data.loc[Data.Group.eq(1), 'impact'] = 
 [(Data.Price.iloc[b] - Data.Price.iloc[a]) for (a,b) in j] 

Однако, если условие не выполняется ни в одной строке, я получил следующую ошибку:

 IndexError: single positional indexer is out-of-bounds

Например, давайте снова посмотрим на мои данные. Как видите, значение группы равно 1 в 8-й строке (цена = 101). Хотя у меня есть значение в 6-й строке (t-2), у меня не было 10-й (t + 2) строки, потому что данные имеют 9 строк.

Я хочу разработать код, который использует ближайшее значение, если данные недоступны. Например, как я уже сказал, значение Group равно 1 в 8-й (t) строке. Обычно код должен найти разницу между 6-й и 10-й строкой. Однако, поскольку у меня нет 10-го ряда, я хочу найти разницу между 6-м и 9-м рядами.

Я надеюсь, что смогу это объяснить.

Заранее спасибо за помощь!

1 Ответ

4 голосов
/ 25 апреля 2019

Вы можете использовать ffill и bfill после выполнения shift в столбце «Цена», чтобы получить пропущенные значения, если они выходят за пределы. Сначала создайте маску, в которой столбец «Группа» равен 1. Затем shift значение в «Цене», равное 2 и -2, заполните NaN, сгенерированное операцией сдвига, и выполните вычитание.

#create the mask
mask = df.Group == 1
# create the column Impact
df.loc[mask,'Impact'] = (df.Price.shift(2).bfill() - df.Price.shift(-2).ffill())[mask] 

и вы получите

print (df)
   Group  Price  Impact
0      0    102     NaN
1      0    103     NaN
2      0    105     NaN
3      1    106    -5.0
4      0    104     NaN
5      0    108     NaN
6      1    101    -3.0
7      0    107     NaN

вы можете использовать fillna, чтобы заменить все значения Nan в Impact тем, что вы хотите

Благодаря @ Скотту Бостону , который добавил комментарий, вы можете использовать метод mask, чтобы сделать это в одной строке:

df['Impact'] = (df.Price.shift(2).bfill() - 
                      df.Price.shift(-2).ffill()).mask(df['Group'] != 1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...