Группировать и сдвигать фрейм данных dask - PullRequest
4 голосов
/ 05 мая 2020

Я хотел бы масштабировать некоторые операции, которые я выполняю на pandas фрейме данных, используя dask 2.14. Например, я хотел бы применить сдвиг к столбцу фрейма данных:

import dask.dataframe as dd
data = dd.read_csv('some_file.csv')
data.set_index('column_A')
data['column_B'] = data.groupby(['column_A'])['column_B'].shift(-1)

, но я получаю AttributeError: 'SeriesGroupBy' object has no attribute 'shift'. Я прочитал документацию по dask и увидел, что такого метода нет (пока был in pandas)

Не могли бы вы предложить какую-нибудь действительную альтернативу?

Спасибо

1 Ответ

5 голосов
/ 14 мая 2020

На GitHub есть открытый запрос об этом. По сути, вам придется использовать apply, чтобы обойти это. Я не уверен, влияет ли это на производительность в dask. Существует еще одна заявка, в которой упоминается проблема и указывается, что она находится в pandas, но она была открыта в течение некоторого времени.

Это должно быть эквивалентно операции pandas:

import dask.dataframe as dd
import pandas as pd
import random

df = pd.DataFrame({'a': list(range(10)),
                   'b': random.choices(['x', 'y'], k=10)})

print("####### PANDAS ######")
print("Initial df")
print(df.head(10))
print("................")

pandas_df = df.copy()
print("Final df")

pandas_df['a'] = pandas_df.groupby(['b'])['a'].apply(lambda x: x.shift(-1))

print(pandas_df.head(10))
print()


print("####### DASK ######")
print("Initial df")
dask_df = dd.from_pandas(df, npartitions=1).reset_index()
print(dask_df.head(10))
print("................")

dask_df['a'] = dask_df.groupby(['b'])['a'].apply(lambda x: x.shift(-1))

print("Final df")
print(dask_df.head(10))

Я, очевидно, не могу протестировать подход в dask, поскольку альтернативы, похоже, нет. Тем не менее, я могу в pandas:

import string

import numpy as np
import pandas as pd


df = pd.DataFrame({'a': list(range(100000)),
                   'b': np.random.choice(list(string.ascii_lowercase), 100000)
                   })

def normal_way(df):
    df = df.groupby(['b'])['a'].shift(-1)

def apply_way(df):
    df = df.groupby(['b'])['a'].apply(lambda x: x.shift(-1))

Результаты timeit:

%timeit normal_way(df)
4.25 ms ± 98 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit apply_way(df)
15 ms ± 446 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
...