Я задаюсь вопросом об эффективных и лаконичных способах передачи столбцов с ошибками в результат 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)