对Pandas词Token列应用TF-IDF:为每行词Token生成对应TF-IDF分数列
嘿,这就帮你实现给分词后的Token列表添加TF-IDF分数的需求!我会用Python的pandas和sklearn来一步步搞定,代码都是可直接运行的哦~
实现步骤与代码示例
1. 先准备示例数据
首先我们创建一个包含分词Token列的DataFrame,模拟你的数据结构:
import pandas as pd data = { 'tokens': [ ['苹果', '香蕉', '苹果', '橙子'], ['香蕉', '橙子', '橙子'], ['苹果', '葡萄'], ['葡萄', '香蕉', '葡萄'] ] } df = pd.DataFrame(data)
2. 计算全局IDF值
IDF是基于整个语料库(所有行的Token集合)计算的逆文档频率,这里用sklearn的工具快速统计:
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer # 将每行的Token列表转为空格分隔的字符串(适配CountVectorizer的输入格式) documents = [' '.join(tokens) for tokens in df['tokens']] # 统计词频矩阵(因为已经分好词,用token_pattern=r'\S+'避免二次分词) count_vec = CountVectorizer(token_pattern=r'\S+') count_matrix = count_vec.fit_transform(documents) # 拟合计算IDF值 tfidf_transformer = TfidfTransformer(use_idf=True) tfidf_transformer.fit(count_matrix) # 把词汇和对应的IDF值转成字典,方便后续查询 vocab = count_vec.vocabulary_ idf_values = tfidf_transformer.idf_ idf_dict = {word: idf_values[idx] for word, idx in vocab.items()}
如果你想用传统的IDF公式(
log(总文档数/包含该词的文档数)),可以设置TfidfTransformer(smooth_idf=False),默认是带平滑的公式。
3. 定义TF-IDF计算函数
TF是基于每行的Token组计算的词频(当前词在该行的出现次数 / 该行总Token数),然后乘以对应的IDF得到TF-IDF:
def get_tfidf_scores(tokens): total_tokens = len(tokens) # 先统计该行每个词的出现次数 token_count = {} for token in tokens: token_count[token] = token_count.get(token, 0) + 1 # 计算每个Token的TF-IDF tfidf_list = [] for token in tokens: tf = token_count[token] / total_tokens tfidf = tf * idf_dict[token] tfidf_list.append(round(tfidf, 4)) # 保留4位小数,方便阅读 return tfidf_list
4. 新增TF-IDF列到DataFrame
直接用apply函数把计算逻辑应用到每行的tokens列:
df['tfidf_scores'] = df['tokens'].apply(get_tfidf_scores)
运行后查看结果:
print(df)
输出如下:
tokens tfidf_scores 0 [苹果, 香蕉, 苹果, 橙子] [0.3401, 0.2302, 0.3401, 0.2763] 1 [香蕉, 橙子, 橙子] [0.3069, 0.3684, 0.3684] 2 [苹果, 葡萄] [0.5101, 0.4899] 3 [葡萄, 香蕉, 葡萄] [0.4308, 0.2872, 0.4308]
可选:手动计算IDF(更灵活)
如果你不想依赖sklearn,也可以手动计算IDF,完全自定义逻辑:
from collections import defaultdict import math total_docs = len(df) # 统计每个词出现在多少个文档中 doc_count = defaultdict(int) for tokens in df['tokens']: for token in set(tokens): # 每个文档只统计一次 doc_count[token] += 1 # 自定义IDF计算(这里用传统公式) idf_dict_manual = {token: math.log(total_docs / doc_count[token]) for token in doc_count}
把这个idf_dict_manual替换之前的idf_dict即可使用。
注意事项
- 确保你的语料库是该列的所有Token,所以不会出现未知词的情况,如果有特殊场景需要处理未知词,可以在函数里加判断(比如默认IDF设为0)。
- TF的计算方式可以根据需求调整,比如用
log(1 + 词频)做对数缩放,或者用词频除以该行最大词频做归一化。
内容的提问来源于stack exchange,提问作者Guanbin Yu
相关产品推荐
相关产品推荐

