Я хочу преобразовать такой фрейм данных
date | colA | ColB
------------------------------------
1971-10-01 0.002451 NaN
1971-11-01 0.002445 NaN
1971-12-01 0.002439 NaN
1972-01-01 0.002433 NaN
1972-02-01 0.004854 NaN
1972-03-01 0.000000 250341816.0
1972-04-01 0.002415 NaN
1972-05-01 0.002410 NaN
1972-06-01 0.002404 NaN
к
date | colA | ColB
------------------------------------
1971-10-01 0.002451 0
1971-11-01 0.002445 0
1971-12-01 0.002439 0
1972-01-01 0.002433 0
1972-02-01 0.004854 0
1972-03-01 0.000000 250341816.0
1972-04-01 0.002415 250946391.486
1972-05-01 0.002410 251551172.289
1972-06-01 0.002404 252155901.307
В colB было только одно допустимое значение, т. е. 250341816.0
, а остальные все строки были NaN
, строки над ним должны быть заполнены 0
, а i
-я строка ниже должна быть заполнена
df[ColB].iloc[i] = df[ColB].iloc[i-1] * (1 + df[ColA].iloc[i])
например, как вы можете видеть
250341816.0*(1+0.002415)=250946391.486
Я ищу краткий способ сделать это, желательно не путем явного зацикливания всех индексов.
Выглядит просто как кампрод colA + 1
Код
cond = df['colB'].shift().isna().cummin()
df['colB'] = (
df['colA']
.mask(cond, 0)
.add(1)
.cumprod()
.mul(df['colB'].ffill(), fill_value=0)
)
дф
date colA colB
0 1971-10-01 0.002451 0.000000
1 1971-11-01 0.002445 0.000000
2 1971-12-01 0.002439 0.000000
3 1972-01-01 0.002433 0.000000
4 1972-02-01 0.004854 0.000000
5 1972-03-01 0.000000 250341816.000000
6 1972-04-01 0.002415 250946391.486000
7 1972-05-01 0.002410 251551172.289000
8 1972-06-01 0.002404 252155901.307000
Пример кода
import pandas as pd
data = {'date': ['1971-10-01', '1971-11-01', '1971-12-01', '1972-01-01', '1972-02-01', '1972-03-01', '1972-04-01', '1972-05-01', '1972-06-01'], 'colA': [0.002451, 0.002445, 0.002439, 0.002433, 0.004854, 0.0, 0.002415, 0.00241, 0.002404], 'colB': [float('nan'), float('nan'), float('nan'), float('nan'), float('nan'), 250341816.0, float('nan'), float('nan'), float('nan')]}
df = pd.DataFrame(data)
Короче говоря - нельзя, это должен быть цикл :) stackoverflow.com/questions/38008390/…