寻找对频繁发生的项目的支持

时间:2017-07-05 07:09:20

标签: python pandas

假设我有一个DataFrame,其中每一行都有订单ID和一个项目。我想知道哪些项目最常出现在另一个项目中(可能是项目出现的概率,因为其他项目在那里?)

假设数据是

Build

然后,order_id,item 1,a 1,b 1,c 2,a 2,b 2,d 3,a 3,b 3,e 对获得最高分。

(我确定这有一个技术名称,找不到它:)。

一个可能的输出将是按顺序出现的对的概率,在我们的例子中是这样的:

a,b

2 个答案:

答案 0 :(得分:1)

达到共生矩阵

首先,获取订单,事件的项目组合

In [249]: cross = pd.crosstab(df['order_id'], df['item'])

In [250]: cross
Out[250]:
item      a  b  c  d  e
order_id
1         1  1  1  0  0
2         1  1  0  1  0
3         1  1  0  0  1

然后,做交叉和转置的产品。

In [251]: cross.T.dot(cross)
Out[251]:
item  a  b  c  d  e
item
a     3  3  1  1  1
b     3  3  1  1  1
c     1  1  1  0  0
d     1  1  0  1  0
e     1  1  0  0  1

这使您可以根据order_id与每个其他项目共同出现每个项目。

答案 1 :(得分:0)

您正在尝试计算对各种项目子集的支持。我写了一个通用代码,它找到了对所有组合的支持。

创建数据集

import sys
if sys.version_info[0] < 3: 
    from StringIO import StringIO
else:
    from io import StringIO

import pandas as pd
data = StringIO("""order_id,item
1,a
1,b
1,c
2,a
2,b
2,d
3,a
3,b
3,e""")

df = pd.read_csv(data)

交叉列表

e = pd.crosstab(index=df.order_id, columns=df.item)
e = e.astype('bool')

这就是e看起来

的方式
item    a   b   c   d   e
order_id                    
1   True    True    True    False   False
2   True    True    False   True    False
3   True    True    False   False   True

现在,对于长度从1到唯一项目数的子集的所有组合,我们查询子集中的所有项目是否都为True。

主要逻辑

from itertools import combinations
out = {}
for k  in range(1, len(df.item.unique())):
    combination_len_k = list(combinations(df.item.unique(), k))
    for c in combination_len_k:
        q = " & ".join(list(c))
        out[c] = len(e.query(q))*1./len(e)

这给了我们以下结果。

{('a',): 1.0,
 ('a', 'b'): 1.0,
 ('a', 'b', 'c'): 0.3333333333333333,
 ('a', 'b', 'c', 'd'): 0.0,
 ('a', 'b', 'c', 'e'): 0.0,
 ('a', 'b', 'd'): 0.3333333333333333,
 ('a', 'b', 'd', 'e'): 0.0,
 ('a', 'b', 'e'): 0.3333333333333333,
 ('a', 'c'): 0.3333333333333333,
 ('a', 'c', 'd'): 0.0,
 ('a', 'c', 'd', 'e'): 0.0,
 ('a', 'c', 'e'): 0.0,
 ('a', 'd'): 0.3333333333333333,
 ('a', 'd', 'e'): 0.0,
 ('a', 'e'): 0.3333333333333333,
 ('b',): 1.0,
 ('b', 'c'): 0.3333333333333333,
 ('b', 'c', 'd'): 0.0,
 ('b', 'c', 'd', 'e'): 0.0,
 ('b', 'c', 'e'): 0.0,
 ('b', 'd'): 0.3333333333333333,
 ('b', 'd', 'e'): 0.0,
 ('b', 'e'): 0.3333333333333333,
 ('c',): 0.3333333333333333,
 ('c', 'd'): 0.0,
 ('c', 'd', 'e'): 0.0,
 ('c', 'e'): 0.0,
 ('d',): 0.3333333333333333,
 ('d', 'e'): 0.0,
 ('e',): 0.3333333333333333}

仅打印长度为2的组合

如果您只想打印长度为两种组合,可以修改for k in range(1, len(df.item.unique())):并通过设置k=2来删除循环。那个案子的答案是:

pd.Series(out)

a  b    1.000000
   c    0.333333
   d    0.333333
   e    0.333333
b  c    0.333333
   d    0.333333
   e    0.333333
c  d    0.000000
   e    0.000000
d  e    0.000000