
在数据分析和处理过程中,我们经常会遇到pandas dataframe中包含超长文本(例如描述、评论、文章内容等)的列。这些文本的长度可能远超某些系统或数据库的字段限制,导致数据导入或后续处理出现问题。常见的需求是将这些长文本拆分成多个较短的片段。然而,仅仅根据固定长度进行硬性截断往往会破坏文本的语义完整性,例如将一个句子从中间截断。更理想的方案是既要遵守长度限制,又要确保每个分段都以完整的句子结束。
为了实现这一目标,我们需要结合使用Python的自然语言工具包(NLTK)和自定义的逻辑函数。NLTK提供了强大的句子分词(Sentence Tokenization)能力,可以将长文本精确地拆分成独立的句子。在此基础上,我们可以设计一个函数来累积这些句子,直到它们的总长度接近或达到预设的最大长度限制,然后将累积的句子作为一个分段输出,并开始新的分段。
以下是实现上述逻辑的关键函数:
import pandas as pd
import nltk
# 确保NLTK的punkt分词器已下载
try:
nltk.data.find('tokenizers/punkt')
except nltk.downloader.DownloadError:
nltk.download('punkt')
def split_sentences(text, max_len=300, prefix='col'):
"""
将长文本按句子和最大长度限制进行拆分。
Args:
text (str): 待拆分的原始长文本。
max_len (int): 每个分段的最大字符长度。
prefix (str): 生成新列名的前缀。
Returns:
pd.Series: 包含拆分后文本片段的Series,其索引将作为新列名的一部分。
"""
out = [] # 存储最终的文本分段
tmp = [] # 临时存储当前分段中的句子
current_len = 0 # 当前分段的累计长度
# 使用NLTK进行句子分词
sentences = nltk.sent_tokenize(text)
for sentence in sentences:
# 考虑句子之间的空格,通常在join时添加
sentence_with_space_len = len(sentence) + (1 if tmp else 0) # 只有非空tmp才加空格长度
# 如果当前句子加入后会超过最大长度限制
# 并且当前分段中已有句子(避免单个句子过长时,将空字符串作为第一个分段)
if current_len + sentence_with_space_len > max_len and tmp:
out.append(' '.join(tmp)) # 将当前累积的句子合并成一个分段
tmp = [] # 重置临时句子列表
current_len = 0 # 重置当前分段长度
# 将当前句子添加到临时列表
tmp.append(sentence)
# 更新当前分段的累计长度
current_len += sentence_with_space_len
# 处理最后一个分段(如果tmp中还有剩余句子)
if tmp:
out.append(' '.join(tmp))
# 将结果转换为Pandas Series,并使用指定前缀和序号命名列
return pd.Series(out).rename(lambda x: f'{prefix}_{x+1}')函数逻辑解析:
有了 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原始文本长度示例:")
print(df['text'].apply(len))应用函数并处理DataFrame:
# 应用split_sentences函数到'text'列
# df['text'].apply(split_sentences) 会为每一行返回一个Series
# df.join() 将这些Series作为新列添加到原始DataFrame中
# drop(columns='text') 移除原始的长文本列
out_df = df.join(df['text'].apply(split_sentences, max_len=300)).drop(columns='text')
print("\n处理后的DataFrame:")
print(out_df)示例输出:
原始DataFrame:
other text
0 1 Lorem ipsum dolor sit amet, consectetur adipis...
1 2 LOREM IPSUM DOLOR SIT AMET, CONSECTETUR ADIPIS...
原始文本长度示例:
0 867
1 867
Name: text, dtype: int64
处理后的DataFrame:
other col_1 \
0 1 Lorem ipsum dolor sit amet, consectetur adipis...
1 2 LOREM IPSUM DOLOR SIT AMET, CONSECTETUR ADIPIS...
col_2 \
0 Proin porttitor, orci nec nonummy molestie, en...
1 PROIN PORTTITOR, ORCI NEC NONUMMY MOLESTIE, EN...
col_3 \
0 Praesent egestas leo in pede. Praesent blandit...
1 PRAESENT EGESTAS LEO IN PEDE. PRAESENT BLANDIT...
col_4
0 Maecenas adipiscing ante non diam sodales hend...
1 MAECENAS ADIPISCING ANTE NON DIAM SODALES HEND... 从输出中可以看到,原始的 text 列已被删除,取而代之的是 col_1, col_2, col_3, col_4 等新列,每个新列都包含长度不超过300字符且保持句子完整性的文本片段。
通过结合NLTK的句子分词能力和自定义的长度累积逻辑,我们成功地解决了Pandas DataFrame中长文本列的智能拆分问题。这种方法不仅满足了长度限制,更重要的是保证了文本分段的语义完整性,极大地提高了数据处理的灵活性和后续利用的便利性。在实际应用中,根据具体的数据特点和性能要求,可以进一步优化和调整此方案。
以上就是Pandas DataFrame长文本列按长度和句子边界智能拆分指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号