如何使用熊猫获得包括每一个组合的计数

共4个回答,已解决, 标签: python pandas

我正在想知道顾客一起买的是什么组合的服装。我可以计算出确切的组合, 但我想不出的问题是包括组合 + 其他的计数。

例如, 我有:

Cust_num  Item    Rev
Cust1     Shirt1  $40
Cust1     Shirt2  $40
Cust1     Shorts1 $40
Cust2     Shirt1  $40
Cust2     Shorts1 $40

这将导致:

Combo                  Count
Shirt1,Shirt2,Shorts1    1
Shirt1,Shorts1           2

我能做的最好的是独特的组合:

Combo                 Count
Shirt1,Shirt2,Shorts1   1
Shirt1,Shorts1          1

我试过了:

df = df.pivot(index='Cust_num',columns='Item').sum()
df[df.notnull()] = "x"
df = df.loc[:,"Shirt1":].replace("x", pd.Series(df.columns, df.columns))
col = df.stack().groupby(level=0).apply(','.join)
df2 = pd.DataFrame(col)
df2.groupby([0]).size().reset_index(name='counts')

但这只是唯一的意义。

第1个答案(采用)

使用 pandas.DataFrame.groupby :

grouped_item = df.groupby('Cust_num')['Item']
subsets = grouped_item.apply(lambda x: set(x)).tolist()
Count = [sum(s2.issubset(s1) for s1 in subsets) for s2 in subsets]
combo = grouped_item.apply(lambda x:','.join(x))
combo = combo.reset_index()
combo['Count']=Count

输出:

  Cust_num                   Item  Count
0    Cust1  Shirt1,Shirt2,Shorts1      1
1    Cust2         Shirt1,Shorts1      2
第2个答案

延迟回答, 但您可以使用:

df = df.groupby(['Cust_num'], as_index=False).agg(','.join).drop(columns=['Rev']).set_index(['Item']).rename_axis("combo").rename(columns={"Cust_num": "Count"})
df['Count'] = df['Count'].str.replace(r'Cust','')

combo                   Count
Shirt1,Shirt2,Shorts1     1
Shirt1,Shorts1            2
第3个答案

我认为你需要首先创建项目的组合。

如何获取列表元素的所有可能组合?

我使用了 Dan h回答中的函数。

from itertools import chain, combinations
def all_subsets(ss):
    return chain(*map(lambda x: combinations(ss, x), range(0, len(ss)+1)))

uq_items = df.Item.unique()

list(all_subsets(uq_items))

[(),
 ('Shirt1',),
 ('Shirt2',),
 ('Shorts1',),
 ('Shirt1', 'Shirt2'),
 ('Shirt1', 'Shorts1'),
 ('Shirt2', 'Shorts1'),
 ('Shirt1', 'Shirt2', 'Shorts1')]

并使用 groupby 每个客户得到他们的项目组合。

ls = []

for _, d in df.groupby('Cust_num', group_keys=False):
    # Get all possible subset of items
    pi = np.array(list(all_subsets(d.Item)))

    # Fliter only > 1
    ls.append(pi[[len(l) > 1 for l in pi]])

然后转换为 Series 并使用 value_counts()

pd.Series(np.concatenate(ls)).value_counts()

(Shirt1, Shorts1)            2
(Shirt2, Shorts1)            1
(Shirt1, Shirt2, Shorts1)    1
(Shirt1, Shirt2)             1
第4个答案

我的版本, 我相信更容易理解

new_df = df.groupby("Cust_num").agg({lambda x: ''.join(x.unique())})

new_df ['count'] = range(1, len(new_df ) + 1)

输出:

                            Item      Rev count

Cust_num
Cust1      Shirt1 Shirt2 Shorts1      $40     1
Cust2             Shirt1 Shorts1      $40     2

由于不需要 Rev 该列, 您可以删除它:

new_df = new_df = new_df.drop(columns=["Rev"]).reset_index()

new_df

输出:

  Cust_num                    Item count

0    Cust1   Shirt1 Shirt2 Shorts1     1
1    Cust2          Shirt1 Shorts1     2

这个编辑是通过 @Chris 查看他使用列表理解编写的方法来回应的。他创建了一个集合列表:

[{' Shirt1', ' Shirt2', ' Shorts1'}, {' Shirt1', ' Shorts1'}]

然后下一步找到子集:

for s1 in subsets:
    for s2 in subsets:
        if s2.issubset(s1):
            print("{}: {}".format(s2,s2.issubset(s1)))

输出:

{' Shirt2', ' Shorts1', ' Shirt1'}: True
{' Shorts1', ' Shirt1'}: True
{' Shorts1', ' Shirt1'}: True

你让我解释我自己, 我做到了。然而, 经过思考, 我意识到你的做法也是错误的。因此, 我不是在嘲笑你, 而是感谢你让我思考我的解决方案。也要感谢 @ResidentSleeper 的解决方案。

相关问题

通过随机抽样其他列数据创建新列 如何使用熊猫获得包括每一个组合的计数 如何有效地展开矩阵的值与小块? 如何破坏 Python 对象并释放内存 将具有特殊格式的文本文档转换为熊猫数据框架 用两本字典绘制一只熊猫专栏图