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中使用groupby或pivot在这个pandas数据框中[重复]
Python Pandas DF Pivot 和 Groupby