假设我有一个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
答案 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}
如果您只想打印长度为两种组合,可以修改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