Python: вычисление процентного изменения для каждого столбца в MultiIndex DataFrame в сочетании с groupby - PullRequest
1 голос
/ 25 сентября 2019

У меня есть фрейм данных MultiIndex, где мне нужно вычислять процентное изменение по столбцам.Я использовал apply в сочетании с pd.pct_change.Это работает, пока я не принимаю во внимание внешний уровень MultiIndex с groupby.

# Creat pd.MultiIndex and include some NaNs

rng = pd.date_range(start='2018-12-20', periods=20, name='date')
date = np.concatenate([rng, rng])
perm = np.array([*np.repeat(1, 20), *np.repeat(2, 20)])

d = {'perm': perm,
     'date': date,
     'ser_1': np.random.randint(low=1, high=10, size=[40]),
     'ser_2': np.random.randint(low=1, high=10, size=[40])}

df = pd.DataFrame(data=d)

df.iloc[5:8, 2:] = np.nan
df.iloc[11:13, 2] = np.nan
df.iloc[25:28, 2:] = np.nan
df.iloc[33:37, 3] = np.nan

df.set_index(['perm', 'date'], drop=True, inplace=True)


# Apply pd.pct_change to every column individually in order to take care of the
# NaNs at different positions. Also, use groupby for every 'perm'. This one is
# where I am struggling.

# This is working properly, but it doesn't take into account 'perm'. The first
# two rows of perm=2 (i.e. rows 20 and 21) must be NaN.
chg = df.apply(lambda x, periods:
               x.dropna().pct_change(periods=2).
               reindex(df.index, method='ffill'),
               axis=0, periods=2)

# This one is causing an error:
# TypeError: () got an unexpected keyword argument 'axis'
chg = df.groupby('perm').apply(lambda x, periods:
                               x.dropna().pct_change(periods=2).
                               reindex(df.index, method='ffill'),
                               axis=0, periods=2)

1 Ответ

1 голос
/ 25 сентября 2019

Ошибка " неожиданный аргумент ключевого слова 'axis' " связана с тем, что pandas.DataFrame.apply и pandas.core.groupby.GroupBy.apply это два разных метода с похожими, но разными параметрами: они имеют одно и то же имя, потому что предназначены для выполнения очень похожих задач, но относятся к двум разным классам.
Если вы посмотрите документацию, вы увидите, чтопервый требует параметра axis.Второй нет.

Таким образом, чтобы иметь рабочий код с groupby, просто удалите параметр axis из GroupBy.apply.Так как вы хотите работать столбец за столбцом из-за dropna, вам нужно использовать DataFrame.apply внутри GroupBy.apply:

chg = df.groupby('perm').apply(lambda x:
                           x.apply(lambda y : y.dropna().pct_change(periods=2)
                           .reindex(x.index, method='ffill'),
                           axis=0))

Это производит то, что вы хотите (первые две строки «perm 2»NaN, другие числа равны результату, который вы получите, используя apply без groupby).
Обратите внимание, что я также отредактировал первый аргумент в reindex: это x.index, а не df.index в противном случае вы получите двойной perm индекс в конечном результате.

Последнее замечание, не нужно передавать аргумент period в функцию lambda, если вы устанавливаете его жестко в pc_change.Избыточен.

...