You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何选择合适的数据结构统计文本单词总频次及对应词性标签频次

如何选择合适的数据结构统计文本单词总频次及对应词性标签频次

嘿,这个问题我之前处理语料库的时候刚好碰到过!其实用嵌套的字典结构(或者借助Python标准库collections里的工具简化代码)就能完美解决,既清晰又容易扩展。

先给你理清楚思路:我们需要的是一个「单词→(总出现次数 + 各POS标签的出现次数)」的映射,所以最直接的就是用外层字典存单词,每个单词对应的值要么是一个包含总次数和POS统计的子字典,要么直接用Counter来存POS的计数(再单独存总次数,或者从POS计数里求和也行)。

方案1:用基础嵌套字典(不依赖额外模块)

如果不想引入额外模块,用普通字典就能实现,逻辑也很直观:

首先初始化一个字典,每个单词对应的条目包含总次数和POS标签的计数:

# 结构:{单词: {"total": 总出现次数, "pos": {POS标签: 次数}}}
word_pos_stats = {}

with open(input_filename, "r") as f:
    for line in f:
        line = line.strip()
        if not line:  # 直接跳过空行,比捕获异常更直观
            continue
        try:
            # 从右边分割一次,避免单词里包含/的情况(虽然语料库一般不会有)
            word, pos = line.rsplit('/', 1)
            pos = pos.strip()  # 去掉POS标签里可能的换行符或空格
            
            # 如果单词还没在统计字典里,初始化它的结构
            if word not in word_pos_stats:
                word_pos_stats[word] = {"total": 0, "pos": {}}
            
            # 更新总次数
            word_pos_stats[word]["total"] += 1
            # 更新对应POS标签的次数,用get方法处理首次出现的标签
            word_pos_stats[word]["pos"][pos] = word_pos_stats[word]["pos"].get(pos, 0) + 1
        except ValueError:
            # 处理不符合word/POS格式的行,比如格式错误的行
            print(f"跳过无效行: {line}")
            pass

接下来就是把统计结果写入输出文件,注意要把POS标签按出现次数降序排列(和你给的示例格式一致):

with open(output_filename, "w") as out_f:
    # 遍历每个单词的统计数据
    for word, stats in word_pos_stats.items():
        total_count = stats["total"]
        # 把POS标签和次数按次数从多到少排序
        sorted_pos = sorted(stats["pos"].items(), key=lambda x: -x[1])
        
        # 拼接成需要的行格式:单词 + 总次数 + 每个POS标签+次数的组合
        line_parts = [word, str(total_count)]
        for pos, cnt in sorted_pos:
            line_parts.extend([pos, str(cnt)])
        
        # 用制表符分隔,写入文件
        out_f.write("\t".join(line_parts) + "\n")

方案2:用collections模块简化代码

如果想让代码更简洁,推荐用collections里的defaultdict和Counter,它们能帮你省去很多初始化的判断:

from collections import defaultdict, Counter

# 外层字典:单词 → 内层Counter统计各POS标签的次数
word_pos_counter = defaultdict(Counter)
# 单独存单词的总出现次数(或者也可以从Counter的values求和得到)
word_total_counts = defaultdict(int)

with open(input_filename, "r") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        try:
            word, pos = line.rsplit('/', 1)
            pos = pos.strip()
            # Counter直接支持标签计数的自增
            word_pos_counter[word][pos] += 1
            word_total_counts[word] += 1
        except ValueError:
            print(f"跳过无效行: {line}")
            pass

输出部分和之前逻辑一致,只是取数据的方式稍有不同:

with open(output_filename, "w") as out_f:
    for word, total in word_total_counts.items():
        # 对POS标签按次数降序排序
        sorted_pos = sorted(word_pos_counter[word].items(), key=lambda x: -x[1])
        line_parts = [word, str(total)]
        for pos, cnt in sorted_pos:
            line_parts.extend([pos, str(cnt)])
        out_f.write("\t".join(line_parts) + "\n")

为什么这个结构合适?

这个嵌套的映射结构完全匹配你要统计的层级:

  1. 外层字典直接对应「单词→它的所有统计数据」的关系,方便快速查找每个单词的信息;
  2. 内层的POS计数字典(或Counter)刚好对应「每个标签出现多少次」的需求,和你输出格式里的后续列完全对应;
  3. 后续输出时,只需要把这些层级的数据依次取出拼接,就能完美生成你要的输出格式。

另外,如果你想更简洁,甚至可以把总次数从POS计数的总和里计算出来(sum(word_pos_counter[word].values())),这样可以省去单独的word_total_counts字典,不过单独存总次数会稍微提升一点效率,尤其是处理大语料库的时候。

备注:内容来源于stack exchange,提问作者djeigi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:54:32