【问题标题】:sorting in pandas groupby with two columns用两列在熊猫 groupby 中排序
【发布时间】:2020-04-21 05:52:12
【问题描述】:

我正在尝试用两列对数据框进行分组,并避免使用“sort = False”进行默认排序。但是,我无法做到这一点。

这里是简化的例子

df = pd.DataFrame([
        ['zebra', 1, 10],
        ['zebra', 2, 10],
        ['apple', 3, 20],
        ['apple', 4, 20],
    ],
    columns=['ColA','ColB','ColC'])

df 因此是

    ColA  ColB  ColC
0  zebra     1    10
1  zebra     2    10
2  apple     3    20
3  apple     4    20

我正在使用 pandas (1.0.3) groupby 并禁用键排序

df_agg = df.groupby(by=['ColA','ColB'], sort = False)

df_agg.groups

结果

{('apple', 3): Int64Index([2], dtype='int64'),
 ('apple', 4): Int64Index([3], dtype='int64'),
 ('zebra', 1): Int64Index([0], dtype='int64'),
 ('zebra', 2): Int64Index([1], dtype='int64')}

等同于“sort = True”(默认)

但是,我想要的是如下

{
 ('zebra', 1): Int64Index([0], dtype='int64'),
 ('zebra', 2): Int64Index([1], dtype='int64'),
 ('apple', 3): Int64Index([2], dtype='int64'),
 ('apple', 4): Int64Index([3], dtype='int64')
}

'sort = False' 按一列分组时似乎工作正常。

df_agg = df.groupby(by=['ColA'], sort = False)
df_agg.groups

结果

{'zebra': Int64Index([0, 1], dtype='int64'),
 'apple': Int64Index([2, 3], dtype='int64')}

如果排序仅适用于一列而不适用于元组。我可以根据元组对组 dict 进行排序,但我使用的应用程序需要一个 groupby 对象。我感谢任何有关如何解决此问题的指示。

【问题讨论】:

  • 不能只切换groupby的顺序吗? df.groupby(['ColB', 'ColA']).groups 否则创建一个新的组排序 psuedokey 并首先按该键分组,然后删除该键。
  • @ScottBoston 我试过了。它似乎有同样的问题。理想情况下,我想保持 df 中 colA 的顺序。 psuedokey方法我没试过。
  • 这在我看来像是一个错误,应该在 github 上报告为错误。
  • groupby 对象的groups 属性是一个字典,而不是组顺序的来源。它只是跟踪每个组的索引值。您无法通过查看它来确定它是否“有效”。
  • 换句话说,当您使用sort=False 时,假设groups 属性应该不同是错误的

标签: python pandas


【解决方案1】:

groups 属性是一个字典,NOT 确定了组的顺序。您必须通过一些操作“解析”groupby 对象以确定订单是/曾经是什么。

df.groupby(['ColA', 'ColB'], sort=False, as_index=False).first()

    ColA  ColB  ColC
0  zebra     1    10
1  zebra     2    10
2  apple     3    20
3  apple     4    20

对比

df.groupby(['ColA', 'ColB'], as_index=False).first()

    ColA  ColB  ColC
0  apple     3    20
1  apple     4    20
2  zebra     1    10
3  zebra     2    10

实际查看的地方是 groupby 对象的 ngroup 方法

g1 = df.groupby(['ColA', 'ColB'], sort=False, as_index=False)
g1.ngroup()

0    0
1    1
2    2
3    3
dtype: int64

对比

g2 = df.groupby(['ColA', 'ColB'], as_index=False)
g2.ngroup()

0    2
1    3
2    0
3    1
dtype: int64

【讨论】:

    【解决方案2】:

    让我们使用一个伪排序键,这里我使用pd.factorize 创建一个:

    df.assign(sortkey=pd.factorize(df['ColA'])[0]).groupby(['sortkey', 'ColA', 'ColB']).groups
    

    输出:

    {(0, 'zebra', 1): Int64Index([0], dtype='int64'),
     (0, 'zebra', 2): Int64Index([1], dtype='int64'),
     (1, 'apple', 3): Int64Index([2], dtype='int64'),
     (1, 'apple', 4): Int64Index([3], dtype='int64')}
    

    【讨论】:

    • 我们能以某种方式放弃那个伪密钥吗?
    • 好吧,如果你在做一些小团体的事情,你一定可以 reset_index(level=0, drop=True)。
    猜你喜欢
    • 2019-09-16
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 2021-12-18
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多