Python、pandas 数据框、groupby 列和预先知道的值

Posted

技术标签:

【中文标题】Python、pandas 数据框、groupby 列和预先知道的值【英文标题】:Python, pandas dataframe, groupby column and known in advance values 【发布时间】:2020-10-05 14:59:37 【问题描述】:

考虑这个例子:

>>> import pandas as pd
>>> df = pd.DataFrame(
...     [
...         ['X', 'R', 1],
...         ['X', 'G', 2],
...         ['X', 'R', 1],
...         ['X', 'B', 3],
...         ['X', 'R', 2],
...         ['X', 'B', 2],
...         ['X', 'G', 1],
...     ],
...     columns=['client', 'status', 'cnt']
... )
>>> df
  client status  cnt
0      X      R    1
1      X      G    2
2      X      R    1
3      X      B    3
4      X      R    2
5      X      B    2
6      X      G    1
>>>
>>> df_gb = df.groupby(['client', 'status']).cnt.sum().unstack()
>>> df_gb
status  B  G  R
client
X       5  3  4
>>>
>>> def color(row):
...     if 'R' in row:
...         red = row['R']
...     else:
...         red = 0
...     if 'B' in row:
...         blue = row['B']
...     else:
...         blue = 0
...     if 'G' in row:
...         green = row['G']
...     else:
...         green = 0
...     if red > 0:
...         return 'red'
...     elif blue > 0 and (red + green) == 0:
...         return 'blue'
...     elif green > 0 and (red + blue) == 0:
...         return 'green'
...     else:
...         return 'orange'
...
>>> df_gb.apply(color, axis=1)
client
X    red
dtype: object
>>>  

此代码的作用是 groupby 以获取每个类别(红色、绿色、蓝色)的计数。 比 apply 用于实现确定每个客户端颜色的逻辑(在这种情况下只有一个)。

这里的问题实际上是 groupby 对象可以包含任何 RGB 值的组合。 例如,我可以有 R 和 G 列但没有 B,或者我可以只有 R 列,或者我不会有任何 RGB 列。

由于这个事实,在 apply 函数中,我必须为每一列引入 if 语句,以便对每种颜色进行计数,无论其值是否在 groupby 对象中。

我是否有任何其他选择来强制执行颜色函数的逻辑,使用其他东西而不是以这种(丑陋的)方式应用?

例如,在这种情况下,我提前知道我需要恰好三个类别的计数 - R、G 和 B。我需要按列分组和这三个值之类的东西。

我可以按这三个类别(系列、字典、函数吗?)对数据框进行分组,并且无论它们是否存在于组中,所有三个类别总是得到零或总和?

【问题讨论】:

您能否举例说明您的分组数据框不包含任何 RGB 值或根本不包含任何值的情况? 【参考方案1】:

用途:

#changed data for more combinations

df = pd.DataFrame(
    [
        ['W', 'R', 1],
        ['X', 'G', 2],
        ['Y', 'R', 1],
        ['Y', 'B', 3],
        ['Z', 'R', 2],
        ['Z', 'B', 2],
        ['Z', 'G', 1],
     ],
     columns=['client', 'status', 'cnt']
)
print (df)
  client status  cnt
0      W      R    1
1      X      G    2
2      Y      R    1
3      Y      B    3
4      Z      R    2
5      Z      B    2
6      Z      G    1

然后添加fill_value=0参数,用于将不匹配的值(缺失值)替换为0

df_gb = df.groupby(['client', 'status']).cnt.sum().unstack(fill_value=0)
#alternative
df_gb = df.pivot_table(index='client', 
                       columns='status', 
                       values='cnt', 
                       aggfunc='sum', 
                       fill_value=0)
print (df_gb)
status  B  G  R
client         
W       0  0  1
X       0  2  0
Y       3  0  1
Z       2  1  2

取而代之的是创建了具有 0,1 的所有组合的辅助 DataFrame 函数,并为 output 添加了新列:

from  itertools import product

df1 = pd.DataFrame(product([0,1], repeat=3), columns=['R','G','B'])
#change colors like need
df1['output'] = ['no','blue','green','color2','red','red1','red2','all']
print (df1)
   R  G  B  output
0  0  0  0      no
1  0  0  1    blue
2  0  1  0   green
3  0  1  1  color2
4  1  0  0     red
5  1  0  1    red1
6  1  1  0    red2
7  1  1  1     all

然后将1以上的值替换为1使用DataFrame.clip

print (df_gb.clip(upper=1))
   B  G  R output
0  0  0  1    red
1  0  1  0  green
2  1  0  1   red1
3  1  1  1    all

最后一个用于新的输出列DataFrame.merge,没有on参数,所以在两个DataFrames中通过列的交集连接,这里R,G,B

df2 = df_gb.clip(upper=1).merge(df1)
print (df2)
   B  G  R output
0  0  0  1    red
1  0  1  0  green
2  1  0  1   red1
3  1  1  1    all

【讨论】:

如果初始数据框为 df = pd.DataFrame( [ ['W', 'R', 1], ['X' , 'G', 2] ], columns=['client', 'status', 'cnt'] ) 但在这种情况下有效的是:df.groupby(['client', 'status']).cnt。 sum().unstack().reindex(columns=['R', 'G', 'B']) 这里的关键成分是 reindex(columns=['R', 'G', 'B'])。如果我提前知道列,这将确保它们始终存在于数据框中。

以上是关于Python、pandas 数据框、groupby 列和预先知道的值的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas:在groupby数据框中插入缺失日期、时间序列的行

Python pandas数据框根据条件分组

如何在python中使用groupby或pivot在这个pandas数据框中[重复]

Python Pandas DF Pivot 和 Groupby

使用 pandas 在数据帧上执行 groupby,按计数排序并获取 python 中的前 2 个计数

python--pandas分组聚合