我想知道将讨厌的列传递给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个值、每个组返回所有值或每个组返回一些值的函数更感兴趣。
在索引中隐藏所有所需的传递列
%%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
删除列,稍后再将它们连接回来
%%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)
我觉得你把事情搞得太复杂了。您可以只
groupby
和rank
到vals
列。这将返回与原始pandas.Series
长度相同的df
,因此您可以将列设置为该值。你知道吗相关问题 更多 >
编程相关推荐