>>>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)
Cuando hay diferentes grupos en un marco de datos, al usar groupby
se espera que la función pct_change
se aplique a cada grupo. Sin embargo, la combinación de groupby
con pct_change
no produce el resultado correcto.
Salida:
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()
VERSIONES INSTALADAS
cometer: Ninguno
python: 3.6.3.final.0
bits de pitón: 64
SO: Darwin
Versión del SO: 17.5.0
máquina: x86_64
procesador: i386
byteorder: pequeño
LC_ALL: en_US.UTF-8
IDIOMA: 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: Ninguno
xarray: Ninguno
IPython: 6.1.0
esfinge: 1.6.3
chivo expiatorio: 0.4.1
dateutil: 2.6.1
pytz: 2018.3
blosc: Ninguno
cuello de botella: 1.2.1
tablas: 3.4.2
numexpr: 2.6.2
pluma: ninguna
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: Ninguno
psycopg2: Ninguno
jinja2: 2.9.6
s3fs: Ninguno
fastparquet: Ninguno
pandas_gbq: Ninguno
pandas_datareader: Ninguno
Puedo ver que la función pct_change en groupby.py en la línea ~ 3944 no está implementando esto correctamente. Mientras que el método que anula lo implementa correctamente para un marco de datos. Me gustaría pensar que esto debería ser relativamente sencillo de remediar.
Intentaré un PR por esto. Aunque no he contribuido con pandas antes, veremos si puedo completarlo de manera oportuna.
tal vez relacionado con https://github.com/pandas-dev/pandas/issues/11811
Encontré algo en estas líneas cuando cambia en reversa
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)
El método alternativo le proporciona una salida correcta en lugar de cambiar el 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
Una solución alternativa para esto es usar apply
. Esto debería producir el resultado deseado:
df['%_groupby'] = df.groupby('grp')['a'].apply(lambda x: x.pct_change())
Comentario más útil
Una solución alternativa para esto es usar
apply
. Esto debería producir el resultado deseado:df['%_groupby'] = df.groupby('grp')['a'].apply(lambda x: x.pct_change())