Pandas Dataframe groupby 聚合函数和动态列的最大值和最小值之间的差异
Posted
技术标签:
【中文标题】Pandas Dataframe groupby 聚合函数和动态列的最大值和最小值之间的差异【英文标题】:Pandas Dataframe groupby aggregate functions and difference between max and min of a column on the fly 【发布时间】:2021-01-03 23:03:17 【问题描述】:import pandas as pd
df = 'a': ['xxx', 'xxx','xxx','yyy','yyy','yyy'], 'start': [10000, 10500, 11000, 12000, 13000, 14000]
df = pd.DataFrame(data=df)
df_new = df.groupby("a",as_index=True).agg(
ProcessiveGroupLength=pd.NamedAgg(column='start', aggfunc="count"),
StartMin=pd.NamedAgg(column='start', aggfunc="min"),
StartMax=pd.NamedAgg(column='start', aggfunc="max"),
)
给予
>>>df_new
ProcessiveGroupLength StartMin StartMax
a
xxx 3 10000 11000
yyy 3 12000 14000
如何在飞行中到达下方,因为我认为飞行中会更快。
>>>df_new
ProcessiveGroupLength Diff
a
xxx 3 1000
yyy 3 2000
以下代码给出以下错误消息:
Traceback(最近一次通话最后一次): 文件“”,第 5 行,在 TypeError: 不支持的操作数类型 -: 'str' 和 'str'
df_new = df.groupby("a").agg(
ProcessiveGroupLength=pd.NamedAgg(column='start', aggfunc="count"),
Diff=pd.NamedAgg(column='start', aggfunc="max"-"min"),)
【问题讨论】:
您实际上会感到惊讶,但之后执行减法可能是您最高效的结果。这是因为通过添加另一个聚合器,您要求 pandas 为每个组找到两次最小值和最大值。一次用于 StartMin,一次用于 StartMax,然后在计算 Diff 时再进行 2 次。 @CameronRiddell 谢谢,。事实上,我想以最快速、最有效的方式找到差异。因此我删除了不必要的列。 【参考方案1】:您的解决方案应该由 lambda 函数更改,但我认为如果有很多组或/和大型 DataFrame,这应该像第一个解决方案一样慢。
原因是优化了函数max
和min
以及Series
的向量减法。换句话说,如果不使用 lambda 函数,聚合会更快。
df_new = df.groupby("a").agg(
ProcessiveGroupLength=pd.NamedAgg(column='start', aggfunc="count"),
Diff=pd.NamedAgg(column='start', aggfunc=lambda x: x.max() - x.min()),)
或者你可以使用numpy.ptp
:
df_new = df.groupby("a").agg(
ProcessiveGroupLength=pd.NamedAgg(column='start', aggfunc="count"),
Diff=pd.NamedAgg(column='start', aggfunc=np.ptp),)
print (df_new)
ProcessiveGroupLength Diff
a
xxx 3 1000
yyy 3 2000
性能:取决于数据,这里使用了 1M 行中的 1k 组:
np.random.seed(20)
N = 1000000
df = pd.DataFrame('a': np.random.randint(1000, size=N),
'start':np.random.randint(10000, size=N))
print (df)
In [229]: %%timeit
...: df_new = df.groupby("a",as_index=True).agg(
...: ProcessiveGroupLength=pd.NamedAgg(column='start', aggfunc="count"),
...: StartMin=pd.NamedAgg(column='start', aggfunc="min"),
...: StartMax=pd.NamedAgg(column='start', aggfunc="max"),
...: ).assign(Diff = lambda x: x.pop('StartMax') - x.pop('StartMin'))
...:
69 ms ± 728 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [230]: %%timeit
...: df_new = df.groupby("a").agg(
...: ProcessiveGroupLength=pd.NamedAgg(column='start', aggfunc="count"),
...: Diff=pd.NamedAgg(column='start', aggfunc=lambda x: x.max() - x.min()),)
...:
172 ms ± 1.84 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [231]: %%timeit
...: df_new = df.groupby("a").agg(
...: ProcessiveGroupLength=pd.NamedAgg(column='start', aggfunc="count"),
...: Diff=pd.NamedAgg(column='start', aggfunc=np.ptp),)
...:
171 ms ± 3.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
【讨论】:
您的“assign”解决方案似乎比其他两个解决方案更好。谢谢。 为什么 lambda x: x.pop('StartMax') - x.pop('StartMin') 比 np.ptp 快? @burcak - 我猜在后台使用x.max() - x.min())
@burcak - 分配代替df_new['Diff'] = df_new.pop('StartMax') - df_new.pop('StartMin')
,pop
用于避免在下一步中删除列。以上是关于Pandas Dataframe groupby 聚合函数和动态列的最大值和最小值之间的差异的主要内容,如果未能解决你的问题,请参考以下文章
将 pandas.core.groupby.SeriesGroupBy 转换为 DataFrame
如何将pandas dataframe进行groupby操作后得到的数据结构转换为dataframe?
pandas将初始dataframe基于分组变量拆分为多个新的dataframe使用groupby函数tuple函数dict函数(splitting dataframe multiple)
Dataframe Pandas 聚合和/或 groupby