我有一个如下所示的数据集:
它显示了哪家店铺销售了哪些书籍。
import pandas as pd
books = {'shop': ["A", "B", "C", "D", "E", "A", "B", "C", "D",],
'book_id': [1, 1, 2, 3, 3, 3, 4, 5, 1,]
}
df = pd.DataFrame(books, columns = ['shop', 'book_id'])
打印结果如下:
shop book_id
0 A 1
1 B 1
2 C 2
3 D 3
4 E 3
5 A 3
6 B 4
7 C 5
8 D 1
在这个数据集中,
- 店铺 A 销售的书籍是 1, 3
- 店铺 B 销售的书籍是 1, 4
- 店铺 C 销售的书籍是 2, 5
- 店铺 D 销售的书籍是 3, 1
- 店铺 E 只销售书籍 3
现在,我想要计算Jaccard指数。以 店铺 A 和 店铺 B 为例,A 和 B 总共销售了 三 种不同的书籍(书籍 1, 书籍 3, 书籍 4)。然而,只有 一 种产品(这是产品 1)同时被两家店铺销售。因此,这里的 Jaccard指数 应该是 33.3%(1/3)。
这是所需数据的一个样本:
result = {'shop_1': ["A", "B", "A", "C", "A", "D", "A", "E",],
'shop_2': ["B", "A", "C", "A", "D", "A", "E", "A",],
'jaccard': [33.3, 33.33, 0, 0, 100, 100, 50, 50,]
}
desired_df = pd.DataFrame(result, columns = ['shop_1', 'shop_2', 'jaccard'])
Print shop_1 shop_2 jaccard
0 A B 33.30
1 B A 33.33
2 A C 0.00
3 C A 0.00
4 A D 100.00
5 D A 100.00
6 A E 50.00
7 E A 50.00
. . . .
. . . .
. . . .
有人能帮我实现这个吗?有实现Jaccard指数的库吗?
回答:
如果你的数据集不是很大,你可以使用广播方法:
books = pd.crosstab(df.shop, df.book_id)
# underlying numpy
arr = books.values
common = (arr[None,...] | arr[:,None,:]).sum(-1)
output = (books @ books.T)/common
输出结果:
shop A B C D E
shop
A 1.000000 0.333333 0.0 1.000000 0.5
B 0.333333 1.000000 0.0 0.333333 0.0
C 0.000000 0.000000 1.0 0.000000 0.0
D 1.000000 0.333333 0.0 1.000000 0.5
E 0.500000 0.000000 0.0 0.500000 1.0
为了匹配你期望的输出:
output = (output.stack().rename_axis(['shop_1','shop_2'])
.reset_index(name='jaccard')
.query('shop_1 != shop_2')
)
输出结果:
shop_1 shop_2 jaccard
1 A B 0.333333
2 A C 0.000000
3 A D 1.000000
4 A E 0.500000
5 B A 0.333333
7 B C 0.000000
8 B D 0.333333
9 B E 0.000000
10 C A 0.000000
11 C B 0.000000
13 C D 0.000000
14 C E 0.000000
15 D A 1.000000
16 D B 0.333333
17 D C 0.000000
19 D E 0.500000
20 E A 0.500000
21 E B 0.000000
22 E C 0.000000
23 E D 0.500000