【发布时间】:2018-03-07 17:32:34
【问题描述】:
我想测量 pandas DataFrame 中文本之间的 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 中输入了 NaN 的原始文本,稍后将其删除 -> 需要将其用于整个列的标记化)
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 来计算相似度?
如果我按照此处的建议使用余弦相似度:Cosine Similarity row-wise 我很快就能得到结果。但我坚持用 jaccard 来做这件事。
【问题讨论】:
-
您是否尝试过介绍您的工作?基本上看起来标记化是瓶颈
标签: python pandas scikit-learn similarity sklearn-pandas