【问题标题】:Python group by column and value_counts on all other columnsPython 按列分组并在所有其他列上按 value_counts
【发布时间】:2021-06-10 17:21:56
【问题描述】:

我正在处理这种类型的 df:

import pandas as pd

df = pd.DataFrame({'GROUP': ['A', 'A', 'B', 'B', 'C', 'C','A', 'A', 'B', 'B', 'C', 'C','B', 'B', 'C', 'C','A'], 'CATEGORY': ['ORANGE', 'WHITE', 'WHITE','ORANGE','ORANGE','BLACK', 'WHITE', 'BLACK', 'BROWN','BLACK','ORANGE','BLACK', 'WHITE', 'WHITE', 'WHITE', 'BLACK', 'BLACK'], 
                   'SHAPE':['SQUARE','TRIANGLE','SQUARE','CIRCLE','CIRCLE','CIRCLE','SQUARE','CIRCLE','TRIANGLE','CIRCLE','CIRCLE','SQUARE','CIRCLE','TRIANGLE','CIRCLE','SQUARE','CIRCLE']})

df.head()

  GROUP CATEGORY SHAPE
0   A   ORANGE  SQUARE
1   A   WHITE   TRIANGLE
2   B   WHITE   SQUARE
3   B   ORANGE  CIRCLE
4   C   ORANGE  CIRCLE

我正在尝试按GROUP 进行分组,并对 df 中的所有列进行值计数,保持前 n 次出现。所以这里有一个关于单列的例子:

df.groupby('GROUP')['CATEGORY'].apply(lambda x: x.value_counts(normalize=True).head(2)).to_frame()

               CATEGORY
GROUP       
A      WHITE    0.400000
       BLACK    0.400000
B      WHITE    0.500000
       BROWN    0.166667
C      BLACK    0.500000
       ORANGE   0.333333

但我想要的输出是附加所有的 value_counts,如下所示:

                CATEGORY          SHAPE
GROUP       
A      WHITE    0.400000  CIRCLE   0.400000
       BLACK    0.400000  SQUARE   0.400000 
B      WHITE    0.500000  CIRCLE   0.500000
       BROWN    0.166667  TRIANGLE 0.333333
C      BLACK    0.500000  CIRCLE   0.666667
       ORANGE   0.333333  SQUARE   0.333333  

理想情况下,将列重命名为:

       CATEGORY PERC      SHAPE    PERC
GROUP       
A      WHITE    0.400000  CIRCLE   0.400000
       BLACK    0.400000  SQUARE   0.400000 
B      WHITE    0.500000  CIRCLE   0.500000
       BROWN    0.166667  TRIANGLE 0.333333
C      BLACK    0.500000  CIRCLE   0.666667
       ORANGE   0.333333  SQUARE   0.333333  

有什么想法吗?

【问题讨论】:

  • 你有很多值还是只有形状和类别?
  • 这只是一个例子,在原始 df 中我有多个我想包含的分类变量。

标签: python pandas dataframe group-by


【解决方案1】:
  1. 将每个 groupby GROUP 对象传递给函数。
  2. CATEGORYSHAPE 上计算.value_counts()
  3. CATEGORYSHAPE 连接在一起。 axis=1 对使数据排在同一行很重要。
def group_my_data(x):
    category = x['CATEGORY'].value_counts(normalize=True).rename_axis('CATEGORY').reset_index(name='PERC')
    shape = x['SHAPE'].value_counts(normalize=True).rename_axis('SHAPE').reset_index(name='PERC')
    return pd.concat([category, shape], axis=1).head(2)

df = df.groupby('GROUP', as_index=True).apply(group_my_data).reset_index(level=-1, drop=True)

【讨论】:

  • @Kauber 如果您的组与您想要的输出示例的顺序完全相同,这有关系吗?您会注意到我的解决方案中 A 组中的值被交换了。
【解决方案2】:

你可以使用.stack()

.concat() 在列表组合中处理每个唯一的列类型。 SHAPECATEGORY

但是,此解决方案最多可以处理 n 个唯一类型。

s = df.set_index('GROUP').stack()\
      .groupby(level=[0,1])\
      .value_counts(normalize=True).groupby(level=[0,1]).head(2) #< change 2 for your val.

dfs = pd.concat([s[s.index.isin([i],1)].reset_index()\
                                       .rename(columns={'level_2' : i, 0  : 'PERC'})\
                                       .drop('level_1',1).set_index('GROUP')
                 for i in s.index.get_level_values(1).unique()],axis=1)


print(dfs)

     CATEGORY      PERC     SHAPE      PERC
GROUP                                       
A        BLACK  0.400000    CIRCLE  0.400000
A        WHITE  0.400000    SQUARE  0.400000
B        WHITE  0.500000    CIRCLE  0.500000
B        BLACK  0.166667  TRIANGLE  0.333333
C        BLACK  0.500000    CIRCLE  0.666667
C       ORANGE  0.333333    SQUARE  0.333333

【讨论】:

  • 这个解决方案在第一部分工作得很好,这可能已经足够好了。尽管如此,当我尝试在具有 2+ 列的 df 上应用 pd.concat 部分以运行 value_counts() 时,我得到 ValueError:传递值的形状是 (9, 24),索引意味着 (3, 24)。我不知道是什么问题。
猜你喜欢
  • 1970-01-01
  • 2020-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多