【问题标题】:Groupby pandas dataframe based on custom list of possible values基于可能值的自定义列表的 Groupby pandas 数据框
【发布时间】:2021-10-13 20:24:48
【问题描述】:

我想对两列中的值进行分组。我知道列中所有可能的值。在某些数据示例中,列 a 中的某些值不存在。我仍然希望 groupby 的输出说组的 len 为零。

          s      a  
0  Michaels     FS
1  Michaels     FS
2  Michaels    fds
3  Michaels   fnfe
4  Rogers       FS
5  Rogers      fds
6  Rogers      fds
7  Rogers      ssn

我想对 s 和 a 进行分组。

df.groupby(by=["s", "a"]).size()

如果您查看数据样本,Michaels 和 Rogers 都不存在 fnfe 和 ssn。所以 Michaels-ssn 和 Rogers-fnfe 不会有输出。

我找到了解决这个问题的方法:

df.groupby(by=["s", "a"]).size().unstack().fillna(0).stack()

但后来我发现有可能会有几个 a 的值不在这两个组中,但我仍然在输出中将它们的值设置为零。 s列没有这样的要求。

假设“a”列“adg”有另一个值,该值在任何示例中都不存在。期望的输出是:

s         a   
Michaels  FS      2
          fds     1
          fnfe    1
          ssn     0
          adg     0
Rogers    FS      1
          fds     2
          ssn     1
          fnfe    0
          adg     0

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    Series.reindexMultiIndex.from_product 一起使用,并将值添加到具有唯一值的列表中:

    out = df.groupby(by=["s", "a"]).size()
    
    s = df['s'].unique()
    a = df['a'].unique().tolist() + ['adg']
    
    out = out.reindex(pd.MultiIndex.from_product([s, a], names=['s','a']), fill_value=0)
    
    print (out)
    s         a   
    Michaels  FS      2
              fds     1
              fnfe    1
              ssn     0
              adg     0
    Rogers    FS      1
              fds     2
              fnfe    0
              ssn     1
              adg     0
    dtype: int64
    

    您的解决方案:

    a = df['a'].unique().tolist() + ['adg']
    
    out = (df.groupby(by=["s", "a"]).size()
             .unstack(fill_value=0)
             .reindex(a, fill_value=0, axis=1)
             .stack())
    
    print (out)
    s         a   
    Michaels  FS      2
              fds     1
              fnfe    1
              ssn     0
              adg     0
    Rogers    FS      1
              fds     2
              fnfe    0
              ssn     1
              adg     0
    dtype: int64
    

    另一个想法是使用Categorical:

    df['a'] = pd.Categorical(df['a'], categories=df['a'].unique().tolist() + ['adg'])
    
    out = df.groupby(by=["s", "a"]).size()
    print (out)
    s         a   
    Michaels  FS      2
              fds     1
              fnfe    1
              ssn     0
              adg     0
    Rogers    FS      1
              fds     2
              fnfe    0
              ssn     1
              adg     0
    dtype: int64
    

    【讨论】:

    • 谢谢,非常好的解决方案。我使用的唯一区别是我使用集合来定义类别,因为我不确定是否会丢失一个值。
    猜你喜欢
    • 2018-02-08
    • 1970-01-01
    • 2023-01-11
    • 2021-11-19
    • 1970-01-01
    • 2019-01-03
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多