Pandas DataFrame中NLP文本预处理的正确顺序与类型处理

Pandas DataFrame中NLP文本预处理的正确顺序与类型处理

本文深入探讨在Pandas DataFrame中进行NLP文本预处理时常见的类型不匹配问题及其解决方案。重点阐述了在不同预处理步骤中(如分词、大小写转换、停用词移除、词形还原等)如何正确处理字符串与列表类型数据的转换,并提供了一个结构清晰、类型安全的Python代码示例,以确保预处理流程的顺畅与高效。

引言:NLP文本预处理的挑战

在自然语言处理(nlp)任务中,文本预处理是至关重要的一步,它直接影响后续模型训练的效果和性能。然而,当我们在pandas dataframe中处理文本数据时,常常会遇到一个核心挑战:不同预处理函数对输入数据类型(字符串或字符串列表)的要求不一致,导致 attributeerror 等类型错误。例如,str.split() 方法只能应用于字符串,而不能应用于列表。理解数据在不同处理阶段的类型变化,并采取相应的处理策略,是构建健壮高效预处理管道的关键。

核心问题:类型不匹配与处理顺序

在构建文本预处理流程时,一个常见的错误是将分词(Tokenization)操作过早地应用于DataFrame列,导致列中的每个单元格从单个字符串变为一个单词列表。此后,如果继续使用期望字符串作为输入的函数(例如 contractions.fix()、unidecode() 或 re.sub()),就会引发 AttributeError: ‘list’ object has no attribute ‘split’ 等错误。

正确的处理方式是,一旦数据被分词成列表,后续所有针对单个单词的操作都必须通过遍历列表中的每个单词来完成。这意味着需要将操作封装在列表推导式中,如 [func(word) for word in x],其中 x 是一个单词列表。

构建类型安全的预处理管道

为了解决上述问题并构建一个类型安全的文本预处理管道,我们需要仔细规划每个步骤,并确保函数能够正确处理当前数据类型。

1. 必要的库和资源导入

首先,导入所需的Python库和NLTK资源。

import pandas as pdimport nltkfrom nltk.corpus import stopwordsfrom nltk.stem import WordNetLemmatizerfrom nltk.corpus import wordnetfrom nltk.tokenize import word_tokenizeimport reimport stringfrom unidecode import unidecodeimport contractionsfrom textblob import TextBlob # 注意:TextBlob可能需要单独安装# nltk.download('punkt')# nltk.download('stopwords')# nltk.download('wordnet')# nltk.download('averaged_perceptron_tagger')

2. 辅助函数:智能词形还原(Lemmatization)

词形还原通常需要词性(Part-of-Speech, POS)信息以获得更准确的结果。由于我们的数据在经过分词后将是单词列表,我们需要一个能够接受单词列表并对每个单词进行POS标记和词形还原的辅助函数。

def lemmatize_words(words_list, lemmatizer, pos_tag_dict):    """    对单词列表进行POS标记并执行词形还原。    Args:        words_list (list): 待处理的单词列表。        lemmatizer (nltk.stem.WordNetLemmatizer): WordNet词形还原器实例。        pos_tag_dict (dict): NLTK POS标签到WordNet POS标签的映射字典。    Returns:        list: 词形还原后的单词列表。    """    lemmatized_words = []    # 对整个单词列表进行POS标记,效率更高    pos_tuples = nltk.pos_tag(words_list)    for word, nltk_word_pos in pos_tuples:        # 获取WordNet对应的词性        wordnet_word_pos = pos_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) # 默认动词        lemmatized_words.append(new_word)    return lemmatized_words

3. 主处理函数:processing_steps(df)

这个函数将包含所有预处理步骤,并确保每一步都正确处理数据类型。

def processing_steps(df):    """    对DataFrame中的文本列执行一系列NLP预处理步骤。    Args:        df (pd.DataFrame): 包含文本数据的DataFrame。    Returns:        pd.DataFrame: 预处理后的DataFrame。    """    lemmatizer = WordNetLemmatizer()    # 定义NLTK POS标签到WordNet POS标签的映射    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"] # 确保这些词不会被移除    local_stopwords.update(additional_stopwords)    # 从停用词中移除需要保留的词    for word in words_to_keep:      if word in local_stopwords:        local_stopwords.remove(word)    new_data = {} # 用于存储处理后的数据    for column in df.columns:        # 复制原始列数据进行处理,避免直接修改原始DataFrame        results = df[column].copy()        # 1. 分词 (Tokenization)        # 将每个字符串单元格转换为单词列表        results = results.apply(word_tokenize)        # 从这里开始,'results' 中的每个元素都是一个单词列表。        # 因此,所有后续操作都需要通过列表推导式应用于列表中的每个单词。        # 2. 小写化 (Lowercasing each word within the list)        results = results.apply(lambda x: [word.lower() for word in x])        # 3. 移除停用词 (Removing stopwords)        # 移除非字母字符和停用词        results = results.apply(lambda tokens: [word for word in tokens if word.isalpha() and word not in local_stopwords])        # 4. 替换变音符号 (Replace diacritics)        # unidecode函数期望字符串输入,因此需要对列表中的每个单词应用        results = results.apply(lambda x: [unidecode(word, errors="preserve") for word in x])        # 5. 扩展缩写 (Expand contractions)        # contractions.fix期望字符串输入。这里假设每个“单词”可能包含缩写(如"don't"),        # 并且扩展后可能变成多个词(如"do not")。        # word.split()在这里是为了确保contractions.fix处理的是一个完整的短语,        # 并将可能产生的多个词重新组合。        results = results.apply(lambda x: [" ".join([contractions.fix(expanded_word) for expanded_word in word.split()]) for word in x])        # 6. 移除数字 (Remove numbers)        # re.sub期望字符串输入,对列表中的每个单词应用        results = results.apply(lambda x: [re.sub(r'd+', '', word) for word in x])        # 7. 移除标点符号 (Remove punctuation except period)        # re.sub期望字符串输入,对列表中的每个单词应用        # 保留句号,因为它们可能用于句子的分割或表示缩写        results = results.apply(lambda x: [re.sub('[%s]' % re.escape(string.punctuation.replace('.', '')), '' , word) for word in x])        # 8. 移除多余空格 (Remove double space)        # re.sub期望字符串输入,对列表中的每个单词应用        results = results.apply(lambda x: [re.sub(' +', ' ', word).strip() for word in x]) # .strip()去除首尾空格        # 9. 词形还原 (Lemmatization)        # 使用我们自定义的lemmatize_words函数,它接受一个单词列表        results = results.apply(lambda x: lemmatize_words(x, lemmatizer, pos_tag_dict))        # 10. (可选) 拼写纠错 (Typos correction)        # TextBlob.correct() 通常在完整的句子或段落上表现更好。        # 如果在此阶段应用,它将对每个单词进行纠错,可能效果不佳或效率低下。        # 如果需要,可以考虑在分词前进行,或在所有处理完成后将词列表重新连接成字符串再进行。        # results = results.apply(lambda x: [str(TextBlob(word).correct()) for word in x])        # 将处理后的列存入新字典        new_data[column] = results    # 将处理后的数据转换为新的DataFrame    new_df = pd.DataFrame(new_data)    return new_df

示例用法:

# 创建一个示例DataFramedata = {    'title': ["Don't you love NLP?", "This is an amazing article about ML. I've read it 10 times."],    'body': ["It's really cool. I'm learning a lot. https://example.com", "The author is great! He doesn't skip anything."]}df = pd.DataFrame(data)print("原始DataFrame:")print(df)# 执行预处理processed_df = processing_steps(df.copy()) # 传入副本,避免修改原始dfprint("n预处理后的DataFrame:")print(processed_df)

预处理的最佳实践与注意事项

操作顺序的重要性缩写扩展:contractions.fix() 最好在分词前或在分词后针对每个词进行。如果在分词后进行,需要确保它能处理单个词,并正确处理扩展后可能产生的多个词。大小写转换:通常在早期进行,以便后续操作(如停用词移除)能够正确匹配。停用词、数字、标点移除:通常在分词和大小写转换后进行,因为它们依赖于识别单个词。词形还原/词干提取:通常在分词、大小写转换和POS标记后进行。拼写纠错:TextBlob 等工具在处理完整的句子或较长的文本时效果最佳。如果在分词

以上就是Pandas DataFrame中NLP文本预处理的正确顺序与类型处理的详细内容,更多请关注创想鸟其它相关文章!

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

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

相关推荐

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

    本文深入探讨了在Pandas DataFrame中进行NLP文本预处理时,如何正确处理不同操作间的数据类型转换与处理顺序。核心问题在于许多文本处理函数期望字符串作为输入,而分词等操作会将字符串转换为单词列表,若不进行适当的迭代处理,将导致类型错误。文章通过详细的代码示例和解释,展示了如何利用列表推导…

    2025年12月14日
    000
  • 使用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
  • Django reverse() 函数解析:URL 匹配优先级与重定向问题

    本文深入探讨了 Django 中 reverse() 函数在 URL 匹配时可能遇到的问题,特别是当 URL 模式存在包含关系时,reverse() 函数生成的 URL 可能被错误地匹配到其他视图,导致意外的重定向循环。通过分析具体示例,我们将解释其背后的原因,并提供避免此类问题的解决方案。 在 D…

    2025年12月14日
    000
  • 理解并应用TfidfVectorizer:深入剖析TF-IDF计算原理及参数调优

    本文旨在深入解析scikit-learn库中TfidfVectorizer的TF-IDF计算过程,重点阐述smooth_idf参数对IDF值的影响,并通过实例演示如何调整参数以获得期望的计算结果。同时,澄清TF计算中的常见误解,强调TF-IDF计算流程的整体性,帮助读者更准确地理解和运用TfidfV…

    2025年12月14日
    000
  • 理解并正确使用 TfidfVectorizer 计算 TF-IDF 值

    本文旨在帮助读者理解 TfidfVectorizer 在 scikit-learn 中计算 TF-IDF 值的原理,特别是关于 IDF 的计算方式,以及如何通过调整 smooth_idf 参数来影响计算结果。同时,澄清了 TF 的计算方式,避免混淆。通过本文,读者可以更准确地使用 TfidfVect…

    2025年12月14日
    000
  • 使用 Tornado PeriodicCallback 实现多线程任务

    本文介绍了如何在 Tornado 框架中使用 PeriodicCallback 结合线程池来执行耗时任务,避免阻塞主线程,从而保证应用的响应性。通过 IOLoop.current().run_in_executor() 方法,可以将任务提交到线程池中异步执行,实现并发处理,提高程序的性能和稳定性。 …

    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

发表回复

登录后才能评论
关注微信