为什么 pandas.GroupBy.apply() 在某些情况下会忽略排序标志?

nor*_*ius 5 python dataframe pandas pandas-apply pandas-groupby

何时以及为何忽略DataFrame分组的排序标志pd.GroupBy.apply()?通过一个例子可以最好地理解这个问题。在以下虚拟问题的 4 个等效解决方案中,方法 1 和 4 观察排序标志,而方法 2 和 3 由于某种原因忽略它。

import pandas as pd
import numpy as np 

#################################################
# Construct input data:
cats = list("bcabca")
vals = np.arange(0,10*len(cats),10) 
df = pd.DataFrame({"i": cats, "ii": vals})

# df:
#      i  ii
#   0  b   0
#   1  c  10
#   2  a  20
#   3  b  30
#   4  c  40
#   5  a  50

# Groupby with sort=True
g = df.groupby("i", sort=True)

#################################################
# 1) This correctly returns a sorted series
ret1 = g.apply(lambda df: df["ii"]+1)

# ret1:
#   i
#   a  2    21
#      5    51
#   b  0     1
#      3    31
#   c  1    11
#      4    41

#################################################
# 2) This ignores the sort flag
ret2 = g.apply(lambda df: df[["ii"]]+1)

# ret2:
#      ii
#   0   1
#   1  11
#   2  21
#   3  31
#   4  41
#   5  51

#################################################
# 3) This also ignores the sort flag.
def fun(df):
    df["iii"] = df["ii"] + 1
    return df
ret3 = g.apply(fun)

# ret3
#      i  ii  iii
#   0  b   0    1
#   1  c  10   11
#   2  a  20   21
#   3  b  30   31
#   4  c  40   41
#   5  a  50   51

#################################################
# 4) This, however, respects the sort flag again:
ret4 = {}
for key, dfg in g:
    ret4[key] = fun(dfg)
ret4 = pd.concat(ret4, axis=0)

# ret4:
#        i  ii  iii
#   a 2  a  20   21
#     5  a  50   51
#   b 0  b   0    1
#     3  b  30   31
#   c 1  c  10   11
#     4  c  40   41

Run Code Online (Sandbox Code Playgroud)

这是 pandas 的设计缺陷吗?或者这种行为是故意的吗?pd.DataFrame.groupby()从和的文档来看pd.GroupBy.apply(),我希望解决方案 2 和 3 也能考虑排序标志。他们为什么不呢?

(该问题在 pandas 1.2.4 和 1.4.0 中重现)


更新:方法 2 和 3 的解决方法是首先按分组键对 DataFrame 进行排序。灵感来源:请参阅评论中的链接。

# Approach 2:
df.sort_values("i").groupby("i").apply(lambda df: df[["ii"]]+1)
# Approach 3:
df.sort_values("i").groupby("i").apply(fun)
Run Code Online (Sandbox Code Playgroud)

Der*_*k O 2

我不确定是否将此作为答案或评论发布,因为这是一个猜测,但我认为,如果您在 groupby 之后省略了操作中排序依据的列,那么 pandas 不再“理解”排序依据那个专栏。

在示例 2) 中,ret2 = g.apply(lambda df: df[["ii"]]+1)意味着在您的 lambda 函数中,您将不考虑“i”列,因此 pandas 不再有此列作为排序依据。

在示例 4) 中,您将连接整个 df(包括列),'i'以便 pandas“知道”按该列排序。