我正在使用具有以下结构的DataFrame学习Python /熊猫:
unique_id
我的目标是对上述DataFrame进行一些计算。
具体来说,我想为每个X
:
unique_id count_brands_not_x count_brand_x
0 1 2 0
1 2 2 1
2 3 2 3
的情况下计算品牌数量; 在视觉上,使用上面的示例,我正在寻找的结果DataFrame应该看起来像这样:
groupby
过去,我在简单的示例中使用过groupby
方法,但是我不知道如何在{{1}}中指定条件来解决我遇到的这个新问题。任何帮助,将不胜感激。
答案 0 :(得分:4)
您可以使用GroupBy
和merge
:
maskx = df1['brand'].eq('X')
d1 = df1[~maskx].groupby('unique_id')['brand'].size().reset_index()
d2 = df1[maskx].groupby('unique_id')['brand'].size().reset_index()
df = d1.merge(d2, on='unique_id', how='outer', suffixes=['_not_x', '_x']).fillna(0)
unique_id brand_not_x brand_x
0 1 2 0.00
1 2 2 1.00
2 3 2 3.00
答案 1 :(得分:2)
我在对值pd.crosstab
比较的真假掩码上使用X
s = df1.brand.eq('X')
df_final = (pd.crosstab(df1.unique_id, s)
.rename({False: 'count_brands_not_x' , True: 'count_brand_x'}, axis=1))
Out[134]:
brand count_brands_not_x count_brand_x
unique_id
1 2 0
2 2 1
3 2 3
答案 2 :(得分:1)
您可以对原始DataFrame进行子集化,并为每个计算使用适当的groupby
操作。 concat
加入结果。
import pandas as pd
s = df1.brand.eq('X')
res = (pd.concat([df1[~s].groupby('unique_id').brand.nunique().rename('unique_not_X'),
df1[s].groupby('unique_id').size().rename('count_X')],
axis=1)
.fillna(0))
# unique_not_X count_X
#unique_id
#1 2 0.0
#2 2 1.0
#3 2 3.0
如果您只希望行数不是“ X”的品牌而不是“ unique_brands”,那么我们可以执行单个groupby
和unstack
的结果。
(df1.groupby(['unique_id', df1.brand.eq('X').map({True: 'count_X', False: 'count_not_X'})])
.size().unstack(-1).fillna(0))
#brand count_X count_not_X
#unique_id
#1 0.0 2.0
#2 1.0 2.0
#3 3.0 2.0
答案 3 :(得分:1)
我先创建组,然后再对组中的元素进行计数
但是也许有更好的功能可以对agg()
中的项目进行计数
import pandas as pd
df1 = pd.DataFrame({'unique_id' : [1, 1, 2, 2, 2, 3, 3, 3, 3, 3],
'brand' : ['A', 'B', 'A', 'C', 'X', 'A', 'C', 'X', 'X', 'X']})
g = df1.groupby('unique_id')
df = pd.DataFrame()
df['count_brand_x'] = g['brand'].agg(lambda data:sum(data=='X'))
df['count_brands_not_x'] = g['brand'].agg(lambda data:sum(data!='X'))
df = df.reset_index()
print(df)
编辑:如果我有df['count_brand_x']
,其他人也可以计数
df['count_brands_not_x'] = g['brand'].count() - df['count_brand_x']