pandas dataFrame中文本的Jaccard相似性



我想测量熊猫数据框架中文本之间的jaccard相似性。更确切地说,我有一些实体组,并且在一段时间内为每个实体都有一些文本。我想随着时间的推移分析文本相似性(在这里的jaccard相似性中),分别为每个实体分析。

一个最小的例子来说明我的观点:


import pandas as pd
entries = [
    {'Entity_Id':'Firm1', 'date':'2001-02-05', 'text': 'This is a text'},
    {'Entity_Id':'Firm1', 'date':'2001-03-07', 'text': 'This is a text'},
    {'Entity_Id':'Firm1', 'date':'2003-01-04', 'text': 'No similarity'},
    {'Entity_Id':'Firm1', 'date':'2007-10-12', 'text': 'Some similarity'},
    {'Entity_Id':'Firm2', 'date':'2001-10-10', 'text': 'Another firm'},
    {'Entity_Id':'Firm2', 'date':'2005-12-03', 'text': 'Another year'},
    {'Entity_Id':'Firm3', 'date':'2002-05-05', 'text': 'Something different'}
    ]
df = pd.DataFrame(entries)

entity_id日期文本

Firm1   2001-02-05   'This is a text' 
Firm1   2001-03-07   'This is a text'
Firm1   2003-01-04   'No similarity'
Firm1   2007-10-12   'Some similarity'
Firm2   2001-10-10   'Another firm'
Firm2   2005-12-03   'Another year'
Firm3   2002-05-05   'Something different'

我所需的输出将是这样的:

entity_id日期文本jaccard

Firm1   2001-02-05   'This is a text'       NaN
Firm1   2001-03-07   'This is a text'       1
Firm1   2003-01-04   'No similarity'        0
Firm1   2007-10-12   'Some similarity'      0.33
Firm2   2001-10-10   'Another firm'         NaN 
Firm2   2005-12-03   'Another year'         0.33  
Firm3   2002-05-05   'Something different'  NaN 

也就是说,我喜欢比较一组公司中的所有文本元素,而不管文本之间的时间间隔如何。我想将其始终与以前的文本进行比较。因此,每个公司的第一个条目始终是空的,因为没有文字可比较。

我的方法是将实体标识符的文本缩短一个时间间隔(下一个可用日期)。然后确定每个实体的第一个报告并标记该报告。(我在text_shifted中输入nans的原始文本,然后以稍后将其删除。

df = df.sort_values(['Entity_Id', 'date'], ascending=True)
df['text_shifted'] = df.groupby(['Entity_Id'])['text'].shift(1)
df['IsNaN'] = df['text_shifted'].isnull().astype(int)
df['text_shifted'] = df['text_shifted'].fillna(df['text'])

在以下内容中,我使用jaccard相似性,如下:

def jaccard_similarity(query, document):
    intersection = set(query).intersection(set(document))
    union = set(query).union(set(document))
    return len(intersection)/len(union)

但是,我必须先将输入标记。但是,如果我做类似的事情:

import nltk
df['text_tokens'] = df.text.apply(nltk.word_tokenize)
df['shift_tokens'] = df.text_shifted.apply(nltk.word_tokenize)

在一个非简化的文本示例中,需要数年才能将这些文本归为大约5000个单词,而我有大约100 000个文本。

有什么办法可以加快流程?我可以避免使用令牌化还是更好地使用Sklearn来计算相似性?

如果我使用此处建议的余弦相似性:余弦相似性行,我会很快获得结果。但是我与jaccard一起工作。

加快该过程的一种方法可以是使用射线上的pandas并行处理。

您可以尝试使用jaccard_distance的NLTK实现Jaccard相似性。不过,我找不到处理时间的显着改善(用于计算相似性),在较大的数据集上可能会更好地工作。

尝试将NLTK实现与您的自定义JACCARD相似性函数进行比较(在200个平均长度4个单词/令牌的文本样本上)

ntlk jaccard_distance:

CPU times: user 3.3 s, sys: 30.3 ms, total: 3.34 s
Wall time: 3.38 s

自定义jaccard相似性实现:

CPU times: user 3.67 s, sys: 19.2 ms, total: 3.69 s
Wall time: 3.71 s

相关内容

  • 没有找到相关文章

最新更新