Быстрее `pandas .DataFrame.groupby ()`, когда у вас есть * много * групп - PullRequest
0 голосов
/ 14 апреля 2020

Я хотел бы создать списки из столбца группировки DataFrame по индексу. Для выполнения этой задачи я:

  1. Группируем по индексу
  2. Объединяем все элементы в каждой группе в список

Однако, если число группы становятся большими, эта операция становится очень медленной. Вот иллюстративный пример.

Сначала данные :

import random
import uuid

import numpy as np
import pandas as pd

np.random.seed(42)
random.seed(42)

def make_df(nr_level_one: int = 1000, max_nr_paths: int = 10):
    level_one_values = np.arange(nr_level_one)
    count_paths = np.random.randint(1, max_nr_paths+1, size=nr_level_one)
    idx_one = np.repeat(level_one_values, count_paths)
    nr_obs = np.sum(count_paths)
    idx_two = np.arange(nr_obs)
    idx = pd.MultiIndex.from_tuples(
        zip(idx_one, idx_two), names=['one', 'two']
    )

    paths = [str(uuid.UUID(int=random.getrandbits(128))).replace('-', '/')
             for _ in range(nr_obs)]

    return pd.DataFrame(paths, index=idx, columns=['path'])

df = make_df()
df
        path
one two 
0   0   bdd640fb/0667/1ad1/1c80/317fa3b1799d
    1   23b8c1e9/3924/56de/3eb1/3b9046685257
    2   bd9c66b3/ad3c/2d6d/1a3d/1fa7bc8960a9
    3   972a8469/1641/9f82/8b9d/2434e465e150
    4   17fc695a/07a0/ca6e/0822/e8f36c031199
... ... ...
999 5443    fe66c4fa/35ed/ff38/9197/107c89b702ed
    5444    a560c775/58cf/d966/6f11/0436b3c28ec5
    5445    49e785c7/cbd8/715e/ae98/b722cf97b016
    5446    f7eefd84/b31c/8349/5799/2f42351b3e63
    5447    be3de265/d471/8d86/8d36/645980f6c26c
5448 rows × 1 columns

Я хочу объединить все path s на первом уровне индекса в список. Это функция, которая выполняет то, что я хочу :

df.groupby(level='one').agg(list)
    path
one 
0   [bdd640fb/0667/1ad1/1c80/317fa3b1799d, 23b8c1e...
1   [6b65a6a4/8b81/48f6/b38a/088ca65ed389, 4737819...
2   [371ecd7b/27cd/8130/4722/9389571aa876, 1a2a73e...
3   [3139d32c/93cd/59bf/5c94/1cf0dc98d2c1, a9488d9...
4   [29a3b2e9/5d65/a441/d588/42dea2bc372f, ab9099a...
... ...
995 [5dc2fd9b/f1bd/b57b/b8dd/dfc2963ba31c, aa1c5dc...
996 [1e228ade/59c6/7a52/8f80/d1ef4615575c, d60b04a...
997 [f151ff15/a46e/e99e/ae4e/d89fd659d69f, bf5628b...
998 [17a85108/43b9/3b02/7089/8400b2932bfb, 5d15c12...
999 [85e620fe/a44e/b3e1/c5ba/136f594ed61a, afe1d84...
1000 rows × 1 columns

Но по мере увеличения количества групп, это очень очень медленный (хотя кажется, что он масштабируется линейно с количеством групп)

%%timeit
make_df(100000).groupby(level='one').agg(list)
15 s ± 230 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Есть ли более быстрый способ решения той же задачи с pandas?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...