>>>import pandas as pd
>>>import numpy as np
>>>df = pd.DataFrame(data=np.random.rand(8, 1), columns={'a'})
>>>df['grp']=1
>>>df.loc[::2, 'grp']=2
>>>df['%_groupby']=df.groupby('grp')['a'].pct_change()
>>>df['%_shift']=df.groupby('grp')['a'].shift(0)/df.groupby('grp')['a'].shift(1)-1
>>>print(df)
Quando existem grupos diferentes em um dataframe, usando groupby
espera-se que a função pct_change
seja aplicada em cada grupo. No entanto, combinar groupby
com pct_change
não produz o resultado correto.
Resultado:
a grp %_groupby %_shift
0 1.0 2 NaN NaN
1 1.1 1 0.100000 NaN
2 1.2 2 0.090909 0.200000
3 1.3 1 0.083333 0.181818
4 1.4 2 0.076923 0.166667
5 1.5 1 0.071429 0.153846
6 1.6 2 0.066667 0.142857
7 1.7 1 0.062500 0.133333
a grp %_groupby %_shift
0 1.0 2 NaN NaN
1 1.1 1 NaN NaN
2 1.2 2 0.200000 0.200000
3 1.3 1 0.181818 0.181818
4 1.4 2 0.166667 0.166667
5 1.5 1 0.153846 0.153846
6 1.6 2 0.142857 0.142857
7 1.7 1 0.133333 0.133333
pd.show_versions()
VERSÕES INSTALADAS
commit: Nenhum
python: 3.6.3.final.0
python-bits: 64
OS: Darwin
Versão do sistema operacional: 17.5.0
máquina: x86_64
processador: i386
byteorder: pouco
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8
pandas: 0.23.0
pytest: 3.2.1
pip: 10.0.1
setuptools: 36.5.0.post20170921
Cython: 0.26.1
numpy: 1.14.3
scipy: 0.19.1
pyarrow: Nenhum
xarray: Nenhum
IPython: 6.1.0
esfinge: 1.6.3
patsy: 0.4.1
dateutil: 2.6.1
pytz: 2018.3
blosc: nenhum
gargalo: 1.2.1
tabelas: 3.4.2
numexpr: 2.6.2
pena: nenhuma
matplotlib: 2.1.0
openpyxl: 2.4.8
xlrd: 1.1.0
xlwt: 1.2.0
xlsxwriter: 1.0.2
lxml: 4.1.1
bs4: 4.6.0
html5lib: 0,9999999
sqlalchemy: 1.1.13
pymysql: Nenhum
psycopg2: Nenhum
jinja2: 2.9.6
s3fs: nenhum
fastparquet: nenhum
pandas_gbq: Nenhum
pandas_datareader: Nenhum
Posso ver que a função pct_change em groupby.py na linha ~ 3944 não está implementando isso corretamente. Considerando que o método que ele substitui o implementa corretamente para um dataframe. Eu gostaria de pensar que isso deveria ser relativamente simples de remediar.
Vou dar uma olhada em um PR para isso. Embora eu não tenha contribuído para os pandas antes, veremos se consigo concluí-lo em tempo hábil.
talvez relacionado a https://github.com/pandas-dev/pandas/issues/11811
Encontrou algo nesse sentido quando você muda para trás, então
import pandas_datareader.data as web
import pandas as pd
tickers = ['F','AAPL','NFLX','AMZN','GOOG']
df = pd.DataFrame()
for ticker in tickers:
data = web.DataReader(ticker, 'iex', '2018-01-01', '2018-06-01')
data['ticker'] = ticker
df = df.append(data)
df = df.reset_index()
df['5_day_growth'] = df.groupby('ticker').close.pct_change(periods=-5)
df['5_day_growth_alt'] = df.groupby('ticker').close.pct_change(periods=5).shift(-5)
O método alternativo fornece saída correta em vez de alterar o cálculo.
print(df[['date','ticker','close','5_day_growth', '5_day_growth_alt']].head(6))
date ticker close 5_day_growth 5_day_growth_alt
0 2018-01-02 F 12.1939 -0.032115 0.033181
1 2018-01-03 F 12.2903 -0.020717 0.021155
2 2018-01-04 F 12.5022 -0.013672 0.013862
3 2018-01-05 F 12.7141 -0.002268 0.002273
4 2018-01-08 F 12.6659 0.003820 -0.003805
5 2018-01-09 F 12.5985 0.073894 -0.068810
Uma solução alternativa para isso é usar apply
. Isso deve produzir o resultado desejado:
df['%_groupby'] = df.groupby('grp')['a'].apply(lambda x: x.pct_change())
Comentários muito úteis
Uma solução alternativa para isso é usar
apply
. Isso deve produzir o resultado desejado:df['%_groupby'] = df.groupby('grp')['a'].apply(lambda x: x.pct_change())