Pandas DataFrame文本预处理:数据类型与处理顺序深度解析

pandas dataframe文本预处理:数据类型与处理顺序深度解析

本文深入探讨了在Pandas DataFrame中进行NLP文本预处理时,如何正确处理不同操作间的数据类型转换与处理顺序。核心问题在于许多文本处理函数期望字符串作为输入,而分词等操作会将字符串转换为单词列表,若不进行适当的迭代处理,将导致类型错误。文章通过详细的代码示例和解释,展示了如何利用列表推导式在分词后的列表上逐个单词地应用清洗和标准化操作,从而构建一个健壮、高效的文本预处理流程。

核心挑战:数据类型不匹配

在对Pandas DataFrame中的文本数据进行预处理时,一个常见的陷阱是不同预处理步骤对输入数据类型有不同的要求。例如,nltk.word_tokenize函数将一个字符串分解成一个单词列表,而像contractions.fix或unidecode这样的函数通常期望接收一个完整的字符串作为输入。如果在分词后直接将单词列表传递给这些期望字符串的函数,就会引发AttributeError,例如’list’ object has no attribute ‘split’,因为列表对象没有split方法。

解决此问题的关键在于理解Pandas Series.apply() 方法的工作方式:它会逐个元素地将指定函数应用于Series中的每个数据点。因此,如果一个列中的元素是字符串,apply会将字符串传递给函数;如果元素是列表,apply会将列表传递给函数。当我们的数据经过分词后,列中的每个单元格都变成了单词列表,此时后续的字符串操作就需要通过列表推导式来逐个单词地应用。

文本预处理流程与正确的数据类型处理

下面我们将构建一个完整的文本预处理流程,并详细解释每一步如何处理数据类型,确保流程的顺畅执行。

1. 初始化设置

首先,我们需要导入所有必要的库并定义一些全局变量,如停用词、词形还原器等。

import pandas as pdimport nltkfrom nltk.corpus import stopwords, wordnetfrom nltk.stem import WordNetLemmatizerfrom nltk.tokenize import word_tokenizefrom unidecode import unidecodeimport contractionsimport reimport string# from textblob import TextBlob # TextBlob可能在处理单个单词时效率不高或行为不符预期,此处暂时注释# 下载NLTK所需资源try:    nltk.data.find('corpora/stopwords')except nltk.downloader.DownloadError:    nltk.download('stopwords')try:    nltk.data.find('corpora/wordnet')except nltk.downloader.DownloadError:    nltk.download('wordnet')try:    nltk.data.find('taggers/averaged_perceptron_tagger')except nltk.downloader.DownloadError:    nltk.download('averaged_perceptron_tagger')try:    nltk.data.find('tokenizers/punkt')except nltk.downloader.DownloadError:    nltk.download('punkt')# 初始化词形还原器和词性标注映射lemmatizer = WordNetLemmatizer()pos_tag_dict = {"J": wordnet.ADJ, "N": wordnet.NOUN, "V": wordnet.VERB, "R": wordnet.ADV}# 定义停用词local_stopwords = set(stopwords.words('english'))additional_stopwords = ["http", "u", "get", "like", "let", "nan"]words_to_keep = ["i'", " i ", "me", "my", "we", "our", "us"] # 注意:这里的"i'"可能需要进一步处理,例如 "i'm"local_stopwords.update(additional_stopwords)# 确保要保留的词不在停用词列表中for word in words_to_keep:    if word in local_stopwords:        local_stopwords.remove(word)

2. 自定义词形还原函数

这个函数负责对单个单词进行词形还原,并根据其词性进行更精确的处理。

def lemmatize_pos_tagged_text(text, lemmatizer, post_tag_dict):    """    对给定的文本进行分句、小写、分词、词性标注和词形还原。    注意:此函数期望输入为单个字符串(通常是一个句子或一个单词),    在DataFrame的apply中,如果处理的是单词列表,需要确保每次传入的是列表中的一个单词。    """    # 鉴于此函数在后续处理中被应用于单个单词,其内部的分句和分词逻辑需要调整    # 如果text已经是单个单词,则直接处理    if not isinstance(text, str): # 确保输入是字符串        return text # 或者报错,取决于需求    # 简化为处理单个单词的逻辑    word = text.lower() # 确保单词小写    pos_tuples = nltk.pos_tag([word]) # 对单个单词进行词性标注    nltk_word_pos = pos_tuples[0][1] # 获取标注结果    wordnet_word_pos = post_tag_dict.get(nltk_word_pos[0].upper(), None)    if wordnet_word_pos is not None:        new_word = lemmatizer.lemmatize(word, wordnet_word_pos)    else:        new_word = lemmatizer.lemmatize(word)    return new_word

注意:原始lemmatize_pos_tagged_text函数设计为处理整个句子甚至多句文本。但在我们的DataFrame处理流程中,它最终会被应用于已经分词后的单个单词。因此,上述代码对其进行了简化,使其更适合处理单个单词的场景。

3. 核心预处理步骤 processing_steps

这个函数将遍历DataFrame的每一列,并依次应用各种预处理操作。关键在于,当列中的元素变为列表后,所有后续操作都需要通过列表推导式 [func(item) for item in x] 来确保函数作用于列表中的每个单词。

def processing_steps(df):    """    对DataFrame中的文本列进行一系列NLP预处理操作。    参数:    df (pd.DataFrame): 包含文本数据的DataFrame。    返回:    pd.DataFrame: 经过预处理的新DataFrame。    """    new_data = {} # 用于存储处理结果,避免SettingWithCopyWarning    for column in df.columns:        # 1. 分词 (Tokenization)        # 将每个字符串单元格转换为单词列表        results = df[column].apply(word_tokenize)        # 2. 小写转换 (Lowercasing)        # 遍历每个单词列表,将每个单词转换为小写        results = results.apply(lambda x: [word.lower() for word in x])        # 3. 移除停用词和非字母字符 (Stopword Removal & Non-alphabetic Filter)        # 遍历每个单词列表,过滤掉停用词和非字母的单词        results = results.apply(lambda tokens: [word for word in tokens if word.isalpha() and word not in local_stopwords])        # 4. 去除变音符号 (Diacritic Replacement)        # 遍历每个单词列表,对每个单词应用unidecode        results = results.apply(lambda x: [unidecode(word, errors="preserve") for word in x])        # 5. 扩展缩写 (Expand Contractions)        # 遍历每个单词列表,对每个单词应用contractions.fix        # 注意:contractions.fix期望字符串,如果word本身是复合词(如"don't"),word.split()仍会返回单元素列表,        # 但contractions.fix会正确处理。        results = results.apply(lambda x: [contractions.fix(word) for word in x]) # 简化了原有的word.split()        # 6. 移除数字 (Remove Numbers)        # 遍历每个单词列表,对每个单词移除数字        results = results.apply(lambda x: [re.sub(r'd+', '', word) for word in x])        # 7. 移除标点符号 (Remove Punctuation except period, then remove period if it's the only char)        # 遍历每个单词列表,对每个单词移除标点符号 (除了句号,但如果只剩句号也移除)        # 这里需要注意,如果一个单词只包含标点,它可能在前面被isalpha()过滤掉。        # 这里的处理是针对可能残留的标点符号。        results = results.apply(lambda x: [re.sub(r'[%s]' % re.escape(string.punctuation), '', word) for word in x])        # 进一步清理可能因为移除标点而产生的空字符串        results = results.apply(lambda x: [word for word in x if word])        # 8. 移除多余空格 (Remove Extra Spaces)        # 遍历每个单词列表,对每个单词移除多余空格(尽管此时单词通常不含空格)        results = results.apply(lambda x: [re.sub(r' +', ' ', word).strip() for word in x])        # 再次清理可能产生的空字符串        results = results.apply(lambda x: [word for word in x if word])        # 9. 词形还原 (Lemmatization)        # 遍历每个单词列表,对每个单词应用自定义的词形还原函数        results = results.apply(lambda x: [lemmatize_pos_tagged_text(word, lemmatizer, pos_tag_dict) for word in x])        # 将处理后的结果存入新字典        new_data[column] = results    # 从处理后的数据创建新的DataFrame    new_df = pd.DataFrame(new_data)    return new_df

4. 示例用法

为了演示上述代码的运行,我们创建一个示例文本DataFrame:

# 创建一个示例文本DataFramedata = {'title': ["Don't go to that HTTP site.", "It's a great day! 123.", "I'm happy to get this."],        'body': ["The article was really good, I liked it. http://example.com", "Let's meet at 5 p.m. It's awesome.", "U should try it. Nan, it's not bad."]}df = pd.DataFrame(data)print("原始DataFrame:")print(df)# 执行预处理processed_df = processing_steps(df.copy()) # 传入副本以防修改原始dfprint("n预处理后的DataFrame:")print(processed_df)

输出示例:

原始DataFrame:                         title                                               body0  Don't go to that HTTP site.  The article was really good, I liked it. http:...1          It's a great day! 123.                  Let's meet at 5 p.m. It's awesome.2      I'm happy to get this.       U should try it. Nan, it's not bad.预处理后的DataFrame:                           title                         body0                [do, not, go, site]  [article, really, good, like]1                     [great, day]             [let, meet, awesome]2  [i, am, happy, get, this]              [try, not, bad]

注意事项与最佳实践

理解 apply 的机制: DataFrame.apply() 或 Series.apply() 是对每个元素进行操作。当元素是字符串时,函数接收字符串;当元素是列表时,函数接收列表。这是解决类型错误的关键。列表推导式的重要性: 当一个Series的元素是列表时(例如,经过分词后),后续的元素级操作必须通过列表推导式 [func(item) for item in current_list] 来应用到列表中的每个子元素(单词)。操作顺序: 预处理步骤的顺序会影响结果。通常的顺序是:标准化/清理: 小写、去除变音符号、扩展缩写、移除数字、移除标点、移除多余空格。这些操作通常在分词前或分词后逐个单词进行。分词: 将文本分解为单词或子词单元。过滤: 移除停用词、短词、非字母字符等。词形还原/词干提取: 将单词还原为基本形式。性能考量: 某些操作(如TextBlob().correct())可能计算成本较高。在大型数据集上,应谨慎使用或考虑替代方案。在上述代码中,TextBlob被注释掉,因为它可能不适合在每个单词上单独应用,或效率不高。避免原地修改: 在processing_steps函数中,我们创建了一个new_data字典来收集处理结果,最后构建一个新的DataFrame。这比直接修改原始DataFrame的列(如df[column] = …)更安全,可以避免SettingWithCopyWarning。错误处理: 在实际应用中,应考虑更健壮的错误处理机制,例如对空字符串或非字符串类型的数据进行处理。

总结

在Pandas DataFrame中进行NLP文本预处理时,数据类型的管理是至关重要的一环。通过清晰地理解每个预处理步骤对输入数据类型的要求,并灵活运用Pandas的apply方法结合Python的列表推导式,我们可以有效地处理字符串与列表之间的转换,从而构建一个高效且健壮的文本清洗流水线。遵循本文介绍的原则和示例代码,将有助于避免常见的类型错误,并确保文本数据为后续的NLP任务做好准备。

以上就是Pandas DataFrame文本预处理:数据类型与处理顺序深度解析的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1366406.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 05:10:13
下一篇 2025年12月14日 05:10:30

相关推荐

  • 使用pyodbc处理MS Access数据库中的时间数据类型:理解与提取

    当使用pyodbc连接MS Access数据库并查询时间(TIME)字段时,返回的结果通常是包含日期部分的datetime.datetime对象,而非纯粹的HH:MM:SS格式。这是因为Access内部没有独立的TIME类型,而是将其存储为DateTime类型,并以1899年12月30日作为基准日期…

    2025年12月14日
    000
  • Python源码中如何实现闭包结构 探索函数嵌套的作用域与引用

    python闭包的实现基于函数嵌套作用域和变量作用域的legb规则,其核心在于内部函数引用外部函数变量并被返回,即使外部函数执行完毕,该内部函数仍能访问外部变量。1. 闭包通过“cell”对象封装外部变量,使内部函数携带对外部变量的引用;2. 闭包支持工厂函数,用于生成参数不同但行为相似的函数;3.…

    2025年12月14日 好文分享
    000
  • 怎么使用ELKI库实现基于密度的异常检测?

    elki中dbscan的eps和minpts参数直接影响密度定义,eps过小易误报,过大易漏报,minpts过小易形成不稳定簇,过大易割裂真实簇;2. lof通过局部密度偏差识别异常,能捕捉密度不均数据中的相对稀疏点,优于dbscan的全局噪声判断;3. 高维数据面临距离失效与计算复杂度挑战,应对策…

    2025年12月14日 好文分享
    000
  • Pandas中如何实现数据的分类汇总?

    pandas中实现数据分类汇总的核心工具是groupby()方法。1. 使用groupby()按一个或多个列分组数据;2. 通过.agg()方法定义聚合逻辑,如sum()、mean()、count()等;3. 可使用reset_index()或多级索引参数as_index=false来处理汇总后的多…

    2025年12月14日 好文分享
    000
  • 如何用Python源码模拟内置函数行为 仿写核心功能理解源码逻辑

    模拟len()核心是检查对象是否有__len__方法并调用,否则尝试迭代计数并处理异常;2. 模拟range()需支持start/stop/step参数逻辑并用yield实现惰性生成;3. 深入理解python数据模型即对象通过__len__、__iter__等协议与内置函数交互;4. 纯pytho…

    2025年12月14日 好文分享
    000
  • 在 LibreOffice 中使用 Python 处理 ActionEvent

    本文旨在介绍如何在 LibreOffice 中使用 Python 脚本创建带有 ActionEvent 的表单按钮。正如摘要所述,我们将探讨如何添加事件监听器到表单,并讨论一种替代方案,即通过插入和样式化超链接来创建类似按钮的元素。虽然提供的添加事件监听器的方法可能存在一些问题,但它为解决类似问题提…

    2025年12月14日
    000
  • Python中 == 和 > 运算符比较不同数据类型的值的差异

    正如前文所述,Python中 == 和 > 运算符在比较不同数据类型的值时表现出不同的行为。 == 运算符在不同类型间比较时返回 False,而 > 运算符则会抛出 TypeError 异常。接下来,我们将深入探讨这种差异背后的原因。 等于 (==) 运算符:定义明确的比较 == 运算符…

    2025年12月14日
    000
  • Python中 == 和 > 运算符对不同数据类型值的比较差异

    本文旨在解释Python中==(等于)和>(大于)运算符在比较不同数据类型的值时表现出的差异。==运算符在比较不同类型对象时,只要能明确判断两者是否相同,就会返回True或False。而>运算符则要求比较的对象之间存在明确的排序关系,否则会抛出TypeError异常。本文将深入探讨其背后…

    2025年12月14日
    000
  • Python中不同数据类型间的比较:== 和 > 的差异

    正如摘要所述,本文旨在解释Python中 == (等于) 和 > (大于) 运算符在比较不同数据类型的值时表现出的差异。== 运算符在比较不同类型对象时,只要语义上可以判断“是否相同”,通常返回 False,而不会抛出异常。> 运算符则不然,当比较没有明确定义顺序关系的不同类型对象时,会…

    2025年12月14日
    000
  • Python中 == 和 > 运算符在不同数据类型比较时的差异

    本文深入探讨了Python中 ==(相等)和 >(大于)运算符在比较不同数据类型的值时的行为差异。== 运算符旨在检查两个对象是否相同,对于不同类型对象,其结果通常为 False。而 > 运算符则用于比较对象的大小,但并非所有类型都存在明确的大小关系,因此在比较不兼容类型时会引发 Typ…

    2025年12月14日
    000
  • 解决Docker中doctr模型无限期挂起的问题

    本文旨在解决在使用Docker部署FastAPI应用时,doctr模型在容器内无限期挂起的问题。通过检查requirements.txt文件,确保所有必要的依赖项都已正确安装,可以有效避免因依赖缺失导致的程序运行异常。本文提供了一个详细的Dockerfile示例,并强调了在Docker环境下运行深度…

    2025年12月14日
    000
  • Python中 == 和 > 运算符比较不同数据类型的值的行为差异

    本文旨在解释Python中 == (等于) 和 > (大于) 运算符在比较不同数据类型的值时表现出的差异。== 运算符在不同类型之间比较时,如果两者不相等,则返回 False,而 > 运算符在尝试比较某些不兼容的类型时会引发 TypeError。本文将深入探讨这种行为背后的原因,并解释为…

    2025年12月14日
    000
  • 生成随机矩阵:控制行与列和的迭代方法

    本文详细阐述了如何生成一个指定尺寸的随机矩阵,并确保其每行和每列的和都等于一个预设值Z。针对直接归一化无法同时满足行和列条件的问题,文章介绍并实现了迭代缩放算法。通过交替对行和列进行归一化处理,该方法能够有效地使矩阵收敛到满足双重约束的状态,并提供了详细的代码示例和使用注意事项。 1. 引言 在数据…

    2025年12月14日
    000
  • Python Asyncio:优雅地管理与终止长时间运行的任务

    本文旨在探讨在Python asyncio异步编程中,如何有效管理和终止可能长时间阻塞的任务,以避免程序无限期等待。我们将重点介绍 asyncio.wait 和 asyncio.wait_for 这两个关键工具,它们提供了设置任务超时机制的能力。通过详细的代码示例和最佳实践,您将学会如何确保异步应用…

    2025年12月14日
    000
  • Python asyncio并发任务的超时控制与优雅关闭

    本文探讨了在Python asyncio中如何有效管理可能长时间阻塞的并发任务,并实现整体操作的超时控制。针对asyncio.gather在特定场景下的局限性,重点介绍了asyncio.wait方法,它允许设定超时时间,并能区分已完成和未完成的任务,从而实现对未完成任务的优雅取消,确保程序按预期及时…

    2025年12月14日
    000
  • 解决macOS Retina显示器上Tkinter应用性能卡顿问题

    本文详细探讨了macOS Retina显示器上Tkinter应用可能出现的性能卡顿问题。该问题通常源于Tkinter在高分辨率模式下的渲染开销。教程提供了通过修改Python框架的Info.plist文件,将NSHighResolutionCapable键值设为false的解决方案。此方法能有效提升…

    2025年12月14日
    000
  • 生成指定行和列总和的随机矩阵:迭代缩放法

    本文详细介绍了如何使用迭代缩放方法生成一个尺寸为xy的随机矩阵,并确保其每行和每列的和都等于预设值Z。通过交替对行和列进行归一化和缩放,该方法能够有效地收敛到满足所有条件的矩阵,适用于需要精确控制矩阵总和的应用场景。 概述 在数据分析、模拟以及游戏开发等领域,有时我们需要生成一个随机矩阵,但同时又要…

    2025年12月14日
    000
  • 解决VS Code中Python模块导入错误:解释器配置指南

    本文旨在解决在Visual Studio Code中运行Python代码时,常见的“No module named ‘xxx’”错误。该问题通常源于VS Code未能识别或使用正确的Python解释器,导致无法找到已安装的模块。教程将详细指导用户如何识别当前环境的Python…

    2025年12月14日
    000
  • Python asyncio并发任务的超时管理与优雅关闭策略

    本文旨在解决 asyncio.gather 在处理长时间阻塞任务时无法按时终止的问题。通过深入探讨 asyncio.wait 方法,我们将学习如何为并发任务设置全局超时,并有效地管理已完成和未完成的任务。文章将提供详细的代码示例,指导读者如何优雅地取消超时任务,确保异步应用的健壮性和可控性。 异步任…

    2025年12月14日
    000
  • 解决 Visual Studio Code 中 Ursina 模块导入错误

    本教程旨在解决在使用 Visual Studio Code (VS Code) 运行 Ursina 引擎时遇到的 “No module named ‘ursina’” 错误。通常,该问题源于 VS Code 未选择正确的 Python 解释器。本文将引导你找到正确…

    2025年12月14日
    000

发表回复

登录后才能评论
关注微信