0

0

使用Pandas高效识别文本列中最高概率的关键词类别

花韻仙語

花韻仙語

发布时间:2025-09-12 20:29:28

|

494人浏览过

|

来源于php中文网

原创

使用pandas高效识别文本列中最高概率的关键词类别

本文将详细介绍如何利用Pandas和Python的正则表达式及集合工具,高效地计算文本数据中预定义关键词类别的出现概率,并据此为每行文本分配最高概率的关键词类别标签。教程涵盖了文本预处理、词频统计、概率计算及结果输出,旨在提供一个清晰、专业的解决方案。

概述与问题背景

在文本数据分析中,我们经常需要根据文本内容将其归类到预定义的类别中。一种常见的方法是识别文本中特定关键词的出现情况,并根据其频率进行分类。本教程旨在解决这样一个问题:给定一个包含文本内容的Pandas数据帧列以及多个预定义的关键词列表(每个列表代表一个类别),我们需要为数据帧中的每一行文本计算每个关键词类别的“概率”,并最终标记出具有最高概率的关键词类别。这里,“概率”的定义是:某个关键词类别中出现的关键词总数与该行文本中总词数的比值。

例如,如果我们有“水果”、“动物”和“国家”三个关键词类别,并且一段文本中提到了多个水果词汇,那么这段文本很可能属于“水果”类别。此外,解决方案需要能够处理词形变化(例如,“lichies”应匹配“lichi”)和文本中没有匹配关键词的情况。

初始尝试及问题分析

用户在尝试解决此问题时,通常会构建一个函数来计算单行文本的概率,然后使用Pandas的apply方法将其应用到数据帧上。然而,常见的错误包括:

  1. 函数输入参数不匹配: apply方法在默认情况下(或当axis=0时)会将列作为Series传递给函数,而当axis=1时会将行作为Series传递。如果函数内部期望处理整个DataFrame或特定列的名称,则可能导致错误。原始尝试中,函数期望一个包含'content'列的行对象(row['content']),但当apply与axis=1一起使用时,row本身就是一个Series,直接访问row['content']是正确的。然而,更常见的错误是函数设计为处理整个DataFrame,但apply只传递部分数据。
  2. 效率问题: 在一个循环中反复检查每个单词是否在关键词列表中,尤其是在文本较长或关键词列表较多的情况下,效率会比较低。
  3. 未充分利用Python内置工具: 词频统计可以使用更高效的数据结构如collections.Counter。

优化方案:基于collections.Counter和re的实现

为了解决上述问题,我们将构建一个更健壮、更高效的函数。核心思路是:

  1. 对文本进行标准化处理(小写、分词)。
  2. 使用collections.Counter快速统计文本中每个单词的出现频率。
  3. 遍历每个关键词类别,利用Counter的统计结果计算该类别的总关键词计数。
  4. 计算概率并找出最高概率的类别。

以下是具体的实现代码和详细解释:

1. 导入所需库

import re
from collections import Counter
import pandas as pd

2. 定义关键词类别

首先,将所有的关键词类别及其对应的关键词存储在一个字典中,方便管理和后续迭代。

labels = {
    'fruits': ['mango', 'apple', 'lichi'],
    'animals':  ['dog', 'cat', 'cow', 'monkey'],
    'country': ['us', 'ca', 'au', 'br'],
}

3. 实现概率计算函数 calculate_probability

这个函数将接收单个文本字符串和关键词类别字典作为输入。

Uni-CourseHelper
Uni-CourseHelper

私人AI助教,高效学习工具

下载
def calculate_probability(text, labels_map):
    # 1. 文本预处理:转换为小写并进行分词
    # re.findall(r'\b\w+\b', ...) 用于提取所有单词,忽略标点符号,
    # 并确保“lichies”能通过词干匹配到“lichi”(如果关键词列表包含词干)
    # 注意:此处我们只是简单地将文本分词,并未进行词干提取或词形还原。
    # 对于“lichies”匹配“lichi”的需求,需要确保关键词列表包含其词干形式。
    # 示例中“lichies”被视为与“lichi”匹配,这通常意味着需要更复杂的词形还原。
    # 但在当前简单匹配模式下,如果关键词是“lichi”,而文本是“lichies”,则不会直接匹配。
    # 为了满足“lichies”匹配“lichi”的需求,需要对文本和关键词都进行词干提取或词形还原。
    # 鉴于原始问题描述,我们将保持简单词匹配,并假设关键词列表已包含处理后的形式或用户接受部分匹配。
    # 如果要实现“lichies”匹配“lichi”,需要使用如NLTK或spaCy进行词形还原。
    # 在本教程中,我们假设关键词列表中的词形是待匹配的精确词形。
    # 原始问题描述中的“lichies”匹配“lichi”可能是一个误解,因为简单的`word in list`无法实现。
    # 为了更接近原始意图,我们可以调整关键词列表或分词逻辑。
    # 考虑到`re.findall(r'\b\w+\b', ...)`会提取完整的单词,我们假设关键词列表中的词是精确匹配的。
    # 如果需要模糊匹配,需要引入额外的NLP库。

    words = re.findall(r'\b\w+\b', str(text).lower()) # 确保text是字符串类型
    word_count = len(words)

    # 如果文本为空,则没有词汇,直接返回NaN
    if word_count == 0:
        return 'NaN'

    # 2. 使用Counter统计文本中每个单词的频率
    counts = Counter(words)

    # 3. 计算每个关键词类别的概率
    probs = {}
    for k, keyword_list in labels_map.items():
        # 统计当前类别中关键词的总出现次数
        # sum(counts[w] for w in keyword_list) 遍历关键词列表,
        # 从counts中获取每个关键词的频率并求和。
        # Counter会为不存在的键返回0,因此无需额外检查。
        category_keyword_count = sum(counts[w] for w in keyword_list)
        probs[k] = category_keyword_count / word_count

    # 4. 找出具有最高概率的类别
    # max(probs, key=probs.get) 返回字典中值最大的键
    max_label = max(probs, key=probs.get)

    # 5. 返回结果:如果最高概率大于0,则返回对应的类别标签,否则返回'NaN'
    return max_label if probs[max_label] > 0 else 'NaN'

关于“lichies”匹配“lichi”的说明: 原始问题中提到“Avoid exact string matching. For example: I like lichies too, here lichi keyword will be counted.”。这通常需要进行词干提取(stemming)或词形还原(lemmatization)。然而,在不引入额外NLP库(如NLTK或spaCy)的情况下,仅通过re.findall(r'\b\w+\b', ...)和简单的word in list检查,无法实现“lichies”自动匹配到“lichi”。如果需要此功能,建议:

  • 预处理关键词列表和文本: 在进行匹配前,对文本中的每个词和关键词列表中的每个词都进行词形还原。
  • 调整关键词列表: 确保关键词列表包含可能的词形变体,例如['lichi', 'lichies']。
  • 使用模糊匹配库: 引入fuzzywuzzy等库进行模糊字符串匹配,但这会增加复杂性和计算成本。 在本教程的实现中,我们假设关键词列表中的词是待匹配的精确词形,因此“lichies”不会匹配“lichi”,除非关键词列表中包含“lichies”。 如果用户需要更高级的词形匹配,则需要扩展此解决方案。

4. 构建示例数据帧

data = {
    'content': [
        'My favorite fruit is mango. I like lichies too. I live in au. Cows are domistic animals.',
        'I own RTX 4090...',
        'There is political colfict between us and ca.',
        'au, br mango, lichi apple,.... \n cat, cow, monkey donkey dogs'
    ]
}
df = pd.DataFrame(data)
print("原始数据帧:")
print(df)
print("-" * 30)

5. 应用函数到数据帧

使用Pandas的apply方法将calculate_probability函数应用到content列。注意,这里不再需要axis=1,因为函数设计为处理单个文本字符串。

df['label'] = df['content'].apply(calculate_probability, labels_map=labels)

这里labels_map=labels是apply方法传递额外参数给被应用函数的方式。

6. 查看结果

print("\n处理后的数据帧:")
print(df)

完整示例代码

import re
from collections import Counter
import pandas as pd

# 1. 定义关键词类别
labels = {
    'fruits': ['mango', 'apple', 'lichi'],
    'animals':  ['dog', 'cat', 'cow', 'monkey'],
    'country': ['us', 'ca', 'au', 'br'],
}

# 2. 实现概率计算函数
def calculate_probability(text, labels_map):
    # 确保text是字符串类型,并转换为小写进行分词
    words = re.findall(r'\b\w+\b', str(text).lower())
    word_count = len(words)

    if word_count == 0:
        return 'NaN'

    # 使用Counter统计文本中每个单词的频率
    counts = Counter(words)

    probs = {}
    for k, keyword_list in labels_map.items():
        # 统计当前类别中关键词的总出现次数
        category_keyword_count = sum(counts[w] for w in keyword_list)
        probs[k] = category_keyword_count / word_count

    # 找出具有最高概率的类别
    max_label = max(probs, key=probs.get)

    # 如果最高概率大于0,则返回对应的类别标签,否则返回'NaN'
    return max_label if probs[max_label] > 0 else 'NaN'

# 3. 构建示例数据帧
data = {
    'content': [
        'My favorite fruit is mango. I like lichies too. I live in au. Cows are domistic animals.',
        'I own RTX 4090...',
        'There is political colfict between us and ca.',
        'au, br mango, lichi apple,.... \n cat, cow, monkey donkey dogs',
        '' # 测试空字符串
    ]
}
df = pd.DataFrame(data)

print("原始数据帧:")
print(df)
print("-" * 30)

# 4. 应用函数到数据帧
df['label'] = df['content'].apply(calculate_probability, labels_map=labels)

# 5. 查看结果
print("\n处理后的数据帧:")
print(df)

输出结果:

原始数据帧:
                                             content
0  My favorite fruit is mango. I like lichies too...
1                                  I own RTX 4090...
2      There is political colfict between us and ca.
3  au, br mango, lichi apple,.... \n cat, cow, mo...
4                                                   
------------------------------

处理后的数据帧:
                                             content    label
0  My favorite fruit is mango. I like lichies too...   fruits
1                                  I own RTX 4090...      NaN
2      There is political colfict between us and ca.  country
3  au, br mango, lichi apple,.... \n cat, cow, mo...   animals
4                                                       NaN

注意: 示例输出中,第四行'au, br mango, lichi apple,.... \n cat, cow, monkey donkey dogs'的标签是animals。这是因为在该行文本中,animals类别的关键词(cat, cow, monkey, dogs)有4个,而fruits类别(mango, lichi, apple)有3个,country类别(au, br)有2个。因此animals的概率最高。

注意事项与总结

  1. 文本预处理: re.findall(r'\b\w+\b', ...)是一种有效的词汇提取方法,它能捕获单词边界内的字母数字字符,从而忽略标点符号。str(text).lower()确保了所有文本都转换为小写,避免了大小写不敏感的匹配问题。
  2. 效率提升: collections.Counter在统计词频方面非常高效,因为它在一次遍历中构建了所有词的频率映射,后续对关键词列表的遍历可以直接进行O(1)的查找,而不是重复扫描整个文本。
  3. apply的正确使用: 当函数设计为处理Series中的单个元素时,直接使用df['column'].apply(func, **kwargs)即可,无需axis=1。**kwargs用于向函数传递额外的固定参数,如本例中的labels_map。
  4. 空文本处理: 在calculate_probability函数中,增加了对word_count == 0的检查,确保当文本为空或无法提取任何单词时,返回'NaN',避免除以零的错误。
  5. 概率相等时的处理: max()函数在遇到多个最大值时,会返回它遇到的第一个最大值对应的键。如果需要特定的 tie-breaking 逻辑,需要额外实现。
  6. 词形匹配的局限性: 如前所述,本教程的实现没有包含复杂的词干提取或词形还原。如果您的应用场景对词形变化(如单复数、动词时态)的匹配有严格要求,请考虑引入NLTK或spaCy等自然语言处理库进行预处理。

通过本教程介绍的方法,您可以高效且专业地处理Pandas数据帧中的文本分类任务,根据关键词的概率为每行文本分配最合适的类别标签。此方案具有良好的可读性和扩展性,适用于各种文本分析场景。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

510

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

251

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

745

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

213

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

351

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

236

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

530

2023.12.06

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

9

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.3万人学习

Django 教程
Django 教程

共28课时 | 3.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号