如何在Python中计算Jaccard索引?

如何在Python中计算Jaccard索引?,python,pandas,machine-learning,Python,Pandas,Machine Learning,我有一个如下所示的数据集: 它显示哪本书是哪家商店卖的 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_

我有一个如下所示的数据集:

它显示哪本书是哪家商店卖的

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)。因此,这里的雅卡指数应为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'])

有人能帮我做这个吗?是否有实现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
   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
要匹配您的预期输出:

output = (output.stack().rename_axis(['shop_1','shop_2'])
                .reset_index(name='jaccard')
                .query('shop_1 != shop_2')
         )
输出:

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
   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

Scipy可能会有所帮助:谢谢@PrateekDewan,我试图通过手动键入示例数据来实现它,但由于我是Python的初学者,很难操纵真实数据。非常感谢@Quany Hoang。请允许我问一下‘a’在这里代表什么:common=(a[None,…]| a[:,None,:])。sum(-1)错过了重构,它是上面定义的numpy数组。请参阅更新。Hi@Quang Hoang,我刚刚尝试使用我的真实数据,但不幸的是,内核在运行时已死亡:pd.crosstab(df.shop,df.book_id)你认为这是因为我的数据很大(980 MB)吗?你建议我怎么解决这个问题?@datazang你的数据太大了。你有多少唯一的图书id/商店?有2900万个图书id,但我试图获得类别id(240K)而不是图书id。内核仍在消亡@广亨