Как применить маскировку при создании следующего значения строки, основанного на значении предыдущей строки и другого столбца в Python Pandas? - PullRequest
1 голос
/ 29 мая 2020

Вот данные

import numpy as np
import pandas as pd

data = {
    'cases': [120, 100, np.nan, np.nan, np.nan, np.nan, np.nan],
    'percent_change': [0.03, 0.01, 0.00, -0.001, 0.05, -0.1, 0.003],
    'tag': [7, 6, 5, 4, 3, 2, 1],
}

   cases  percent_change  tag
0  120.0           0.030    7
1  100.0           0.010    6
2    NaN           0.000    5
3    NaN          -0.001    4
4    NaN           0.050    3
5    NaN          -0.100    2
6    NaN           0.003    1

Я хочу создать значение следующего случая как (следующее значение) = (предыдущее значение) * (1 + текущее per_change). В частности, я хочу, чтобы это выполнялось в строках, у которых значение тега меньше 6 (и я должен использовать маску (например, df.loc для этого выбора строки). Это должно дать мне:

   cases  percent_change  tag
0  120.0           0.030    7
1  100.0           0.010    6
2  100.0           0.000    5
3   99.9          -0.001    4
4  104.9           0.050    3
5   94.4          -0.100    2
6   94.7           0.003    1

Я пробовал это, но не работает:

df_index = np.where(df['tag'] == 6)
index = df_index[0][0]
df.loc[(df.tag<6), 'cases'] = (df.percent_change.shift(0).fillna(1) + 1).cumprod() * df.at[index, 'cases']

        cases  percent_change  tag
0  120.000000           0.030    7
1  100.000000           0.010    6
2  104.030000           0.000    5
3  103.925970          -0.001    4
4  109.122268           0.050    3
5   98.210042          -0.100    2
6   98.504672           0.003    1

1 Ответ

1 голос
/ 29 мая 2020

Я бы сделал:

s = df.cases.isna()
percents = df.percent_change.where(s,0)+1
df['cases'] = df.cases.ffill()*percents.cumprod()

Вывод:

        cases  percent_change  tag
0  120.000000           0.030    7
1  100.000000           0.010    6
2  100.000000           0.000    5
3   99.900000          -0.001    4
4  104.895000           0.050    3
5   94.405500          -0.100    2
6   94.688716           0.003    1

Обновление : Если вы действительно настаиваете на маскировке Tag==6:

s = df.tag.eq(6).shift()
s = s.where(s).ffill()

percents = df.percent_change.where(s,0)+1
df['cases'] = df.cases.ffill()*percents.cumprod()
...