如何在pandas DataFrame列上应用自定义函数计算相似度?
pandas 逐行应用word2vec相似度计算函数的异常修复
问题1:直接传入整列生成的相似度值全相同
- 原因:
str(df['title'])不会逐元素把列值转为字符串,而是将整个Series对象转为其固定的字符串表示(包含索引、列名、dtype信息的整列文本拼接结果),所有行计算时传入的input2都是同一个固定字符串,因此返回结果完全一致。
问题2:apply方法触发ZeroDivisionError
- 根因:报错和空字符串无关,触发点是Word2Vec的
n_similarity计算逻辑:该方法会先对两个传入词集合的词向量求均值再计算余弦相似度,如果经过vocab_check词表过滤后,任意一个词集合为空,求均值时分母为0就会抛出除零错误。 - 手动调用前两行数据不报错,是因为'cat'、'dog'刚好都在模型词表中,过滤后集合非空;测试集中其他词(比如'turtle')如果不在加载的词表中,会被
vocab_check过滤掉,导致对应s2words为空集触发报错。
修复方案
- 首先修改相似度计算函数,增加空集合判断逻辑,从根源避免除零错误:
def calc_similarity(input1, input2, vectors): s1words = set(vocab_check(vectors, input1.split())) s2words = set(vocab_check(vectors, input2.split())) # 任意词集合为空时返回默认值,可根据业务调整为np.nan等 if len(s1words) == 0 or len(s2words) == 0: return 0.0 return vectors.n_similarity(s1words, s2words)
- 统一DataFrame变量名(原代码混用了
dat和df),使用apply逐行计算即可:
dat = pd.DataFrame({'title': ['cat', 'dog', 'lion','turtle']}) dat['similarity'] = dat['title'].apply( lambda x: calc_similarity(chosen_article, str(x), model_word2vec) )
辅助排查手段
如果修复后出现大量默认值,可以先打印每个文本经过词表过滤后的剩余词,确认哪些词不在模型词表中:
def get_filtered_words(text, vectors): return set(vocab_check(vectors, str(text).split())) dat['valid_words'] = dat['title'].apply(lambda x: get_filtered_words(x, model_word2vec)) print(dat[['title', 'valid_words']])
内容的提问来源于stack exchange,提问作者Zachqwerty
相关产品推荐
相关产品推荐

