
本文介绍如何利用NLTK和Pandas库,将DataFrame中包含超长描述性文本的列,智能地分割成多个符合指定最大长度限制的新列。该方法确保每个分割后的文本块都以完整的句子结束,有效解决了数据导入导出时字符长度限制的问题,同时保持了文本的语义完整性。
挑战与需求
在数据处理过程中,我们经常会遇到DataFrame中某些文本列(例如产品描述、用户评论等)的字符串长度远超常规限制(如数据库字段限制、API请求体大小限制)。直接截断文本会导致句子不完整,影响语义。因此,一个常见的需求是:
将超长文本列分割成多个子列。每个子列的文本长度不超过一个预设的最大值(例如300个字符)。最关键的是,每个子列的文本都必须以完整的句子结束,避免句子被截断。
传统的基于分隔符或固定长度的分割方法无法同时满足“长度限制”和“句子完整性”这两个条件。
解决方案概述
为了解决上述挑战,我们将结合使用以下工具和策略:
NLTK (Natural Language Toolkit):用于对文本进行句子级别的分词(nltk.sent_tokenize),确保我们能够识别和处理完整的句子。自定义Python函数:编写一个灵活的函数,该函数接收原始长文本和最大长度限制,然后根据NLTK分割的句子,智能地组合成符合长度要求且句子完整的文本块。Pandas apply 和 join 方法:将自定义函数高效地应用到DataFrame的指定列上,并将生成的新列无缝地整合回原始DataFrame。
环境准备
在开始之前,请确保您的Python环境中已安装pandas和nltk库。如果尚未安装,可以通过以下命令进行安装:
pip install pandas nltk
此外,NLTK需要下载其punkt分词器,用于支持sent_tokenize功能。首次使用时,请运行以下代码下载:
import nltknltk.download('punkt')
核心实现:自定义文本分割函数
我们将创建一个名为split_sentences的函数,它接收原始长文本、最大长度限制和新列的前缀作为参数。
import pandas as pdimport nltkdef split_sentences(text, max_len=300, prefix='col'): """ 将长文本按句子边界和最大长度限制分割成多个字符串。 参数: text (str): 待分割的原始文本。 max_len (int): 每个分割块的最大字符长度。 prefix (str): 生成新列的前缀名称。 返回: pd.Series: 包含分割后文本块的Pandas Series,索引为新列名。 """ out = [] # 存储最终的文本块 current_chunk_sentences = [] # 存储当前正在构建的文本块中的句子 current_chunk_len = 0 # 存储当前文本块的实际长度 # 使用NLTK将文本分割成句子 sentences = nltk.sent_tokenize(text) for sentence in sentences: # 计算当前句子加入后,块的长度(包括句子间的空格) # 如果是块中的第一个句子,不加空格;否则加一个空格 sentence_effective_len = len(sentence) + (1 if current_chunk_sentences else 0) # 检查将当前句子加入到当前块是否会超过max_len # 并且确保当前块不为空(避免在第一个句子就超长时创建空块) if current_chunk_len + sentence_effective_len > max_len and current_chunk_sentences: # 如果会超长,则将当前已有的句子组合成一个块并添加到结果中 out.append(' '.join(current_chunk_sentences)) current_chunk_sentences = [] # 清空,开始新的文本块 current_chunk_len = 0 # 重置新块的长度 # 将当前句子添加到当前文本块 current_chunk_sentences.append(sentence) # 更新当前文本块的长度 current_chunk_len += sentence_effective_len # 循环结束后,将最后一个未添加到out的文本块添加进去(如果存在) if current_chunk_sentences: out.append(' '.join(current_chunk_sentences)) # 将结果转换为Pandas Series,并重命名索引为col_1, col_2等 return pd.Series(out).rename(lambda x: f'{prefix}_{x+1}')
函数逻辑详解:
初始化:out列表用于存储最终分割出的文本块,current_chunk_sentences存储当前正在构建的文本块中的句子,current_chunk_len记录当前块的字符总长度。句子分词:使用nltk.sent_tokenize(text)将输入文本分割成独立的句子列表。迭代句子:遍历每个句子。长度检查:在将句子添加到current_chunk_sentences之前,我们计算如果加入该句子,当前块的总长度会是多少。这里需要注意,如果current_chunk_sentences不为空,则在句子之间需要添加一个空格,所以sentence_effective_len会额外加1。块分割判断:如果current_chunk_len + sentence_effective_len超过了max_len,并且current_chunk_sentences不为空(确保不是因为第一个句子就超长而导致空块),则认为当前块已满。此时,将current_chunk_sentences中的所有句子用空格连接起来,形成一个完整的文本块,并添加到out中。然后清空current_chunk_sentences和current_chunk_len,为下一个文本块做准备。添加句子:无论是否发生块分割,当前句子都会被添加到current_chunk_sentences中,并更新current_chunk_len。处理最后一个块:循环结束后,current_chunk_sentences中可能还剩下未添加到out的句子。因此,需要检查并将其作为最后一个文本块添加。返回Series:最终,out列表被转换为一个Pandas Series,其索引被重命名为prefix_1, prefix_2等,方便后续与DataFrame合并。
整合到DataFrame
将上述split_sentences函数应用到DataFrame的指定列,并合并结果。
# 示例数据框lipsum = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit.'''df = pd.DataFrame({'other': [1, 2], 'text': [lipsum, lipsum.upper()]})print("原始DataFrame:")print(df)print("n" + "="*50 + "n")# 应用自定义函数并合并结果# df['text'].apply(split_sentences) 会对'text'列的每个元素(即每个长文本)调用split_sentences函数# 每个调用返回一个Series,df.join() 会将这些Series作为新列添加到DataFrame中# drop(columns='text') 移除原始的长文本列result_df = df.join(df['text'].apply(split_sentences, max_len=300, prefix='text_chunk')).drop(columns='text')print("分割后的DataFrame:")print(result_df)
输出示例:
原始DataFrame: other text0 1 Lorem ipsum dolor sit amet, consectetur adipis...1 2 LOREM IPSUM DOLOR SIT AMET, CONSECTETUR ADIPIS...==================================================分割后的DataFrame: other text_chunk_1
以上就是Pandas DataFrame长文本列按长度和句子边界智能分割教程的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1373965.html
微信扫一扫
支付宝扫一扫