Estou tentando descobrir como usar a função pct_change() do pandas, mas preciso que os valores sejam "envolvidos", para que o último e o primeiro valores criem um valor de alteração percentual na posição 0 em vez de NaN.
Por exemplo:
df = pd.DataFrame({'Month':[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
'Value':[1, 0.9, 0.8, 0.75, 0.75, 0.8, 0.7, 0.65, 0.7, 0.8, 0.85, 0.9]})
Month Value
0 1 1.00
1 2 0.90
2 3 0.80
3 4 0.75
4 5 0.75
5 6 0.80
6 7 0.70
7 8 0.65
8 9 0.70
9 10 0.80
10 11 0.85
11 12 0.90
Usar pct_change() + 1 fornece:
df['percent change'] = df['Value'].pct_change() + 1
Month Value percent change
0 1 1.00 NaN
1 2 0.90 0.900000
2 3 0.80 0.888889
3 4 0.75 0.937500
4 5 0.75 1.000000
5 6 0.80 1.066667
6 7 0.70 0.875000
7 8 0.65 0.928571
8 9 0.70 1.076923
9 10 0.80 1.142857
10 11 0.85 1.062500
11 12 0.90 1.058824
No entanto, também preciso saber a % de mudança entre dezembro (mês=12) e janeiro (mês=1), então o NaN deve ser 1,111111. Espero eventualmente fazer isso para vários grupos dentro de um grupo, então, atrapalhar o preenchimento do Nan com um valor sobre o outro, ou calcular manualmente todas as porcentagens parece uma maneira muito longa de fazer isso. Existe uma maneira mais simples de conseguir isso?
Para obter o comportamento "wrap-around" desejado usando
pct_change()
o Pandas, você pode modificar o DataFrame deslocando temporariamente os valores e preenchendo aNaN
primeira posição com a alteração percentual entre o último e o primeiro valor.Aqui está o código.
Isso pode ser aplicado
groupby()
também.Espero que isso ajude você um pouco.
resumindo;
Explicação
pandas
Series.pct_change
é um wrapper fino em cima de executarSeries / Series.shift(...)
. Como acontece,Series.pct_change
encaminha argumentos de palavra-chave estranhos paraSeries.shift(...)
e este método pega umfill_value
argumento de palavra-chave para preencher valores NaN que resultam da operação de deslocamento. O valor de alteração percentual é então calculado após o.shift
Com o acima exposto em mente, podemos simplesmente especificar
Series.pct_shift(..., fill_value={last row of Series})
Basta usar
numpy.roll
o que foi projetado para esta finalidade específica:Saída:
Se você precisar executar isso por grupo, combine com
groupby.transform
:Saída: