Эффективный и краткий столбец неприятностей GroupBy - PullRequest
0 голосов
/ 24 мая 2018

Я задаюсь вопросом об эффективных и лаконичных способах передачи столбцов с ошибками в результат pandas.DataFrame.groupby. У меня часто есть столбцы, к которым я не хочу применять операцию groupby,но я хочу, чтобы значения распространялись на результат.Пример того, что я пытаюсь сделать, показан ниже

import pandas as pd
import numpy as np
import random
import string

np.random.seed(43)
random.seed(43)

dates = pd.date_range("2015-01-01", "2017-01-02")
types = "AAABBCCCDDDDEEFFFFGG"
rtypes = list(types * len(dates)) 
rdates = dates.tolist() * len(types)

data = np.random.randn(len(rtypes))
info1 = [''.join(random.choice(string.ascii_uppercase) for _ in range(5)) 
         for i in range(len(rtypes))]
info2 = [random.randint(100,1000) for i in range(len(rtypes))]
df = pd.DataFrame({"date": rdates, "category": rtypes, "vals": data, 
                   "info1":info1, "info2": info2})
df = df.sort_values(["date", "category"]).reset_index(drop=True)

df.head()

  category       date  info1  info2      vals
0        A 2015-01-01  BJWYE    990  0.257400
1        A 2015-01-01  ISQES    475 -0.867570
2        A 2015-01-01  KDEKE    214  1.683595
3        B 2015-01-01  TFOXR    203  0.575879
4        B 2015-01-01  HKTNF    992 -0.399677

Здесь я хотел бы сгруппировать по category и date и применить некоторую функцию к vals, но иметь info1и info2 пропущенные столбцы.

Возможные решения

Это возможные решения, которые я нашел, но оба кажутся несколько неуклюжими и имеют совершенно разную производительность, что заставило меня задуматься о том, возможно либолее эффективное или более краткое решение. Я применяю функцию rank в этом примере, но мне более интересно узнать о функциях, которые могут возвращать 1 значение для группы, все значения для группы или некоторые значения для группы.

Параметр1

Сохранение всех нужных проходных столбцов в индексе

%%timeit 

(df.set_index(["date", "category", "info1", "info2"])
 .groupby(axis=0, level=[0, 1]).rank().reset_index())

2.64 s ± 47.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

с результатом

sol1 = (df.set_index(["date", "category", "info1", "info2"])
        .groupby(axis=0, level=[0, 1]).rank().reset_index())
sol1.sort_values(["date", "category"]).head()

        date category  info1  info2  vals
0 2015-01-01        A  BJWYE    990   2.0
1 2015-01-01        A  ISQES    475   1.0
2 2015-01-01        A  KDEKE    214   3.0
3 2015-01-01        B  TFOXR    203   2.0
4 2015-01-01        B  HKTNF    992   1.0

Вариант 2

Удалите столбцы и присоединитесь к нимвернуться позже

%%timeit

pd.merge(
    df.groupby(by=["date", "category"])[["vals"]].rank(),
    df.drop("vals", axis=1),
    how="left",
    left_index=True,
    right_index=True,
)

1.73 s ± 180 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

1 Ответ

0 голосов
/ 24 мая 2018

Я думаю, вы слишком усложняете вещи.Вы можете просто groupby и rank в столбцы vals.Это возвращает pandas.Series той же длины, что и ваш исходный df, так что вы можете просто установить столбец на это.

df['vals'] = df.groupby(['date', 'category']).vals.rank()

  category       date  info1  info2  vals
0        A 2015-01-01  BJWYE    990   2.0
1        A 2015-01-01  ISQES    475   1.0
2        A 2015-01-01  KDEKE    214   3.0
3        B 2015-01-01  TFOXR    203   2.0
4        B 2015-01-01  HKTNF    992   1.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...