Pandas:如何基于逐行单词重构句子字符串
处理百万级别的Pandas DataFrame确实得兼顾效率和准确性,我来给你梳理一套可行的方案,既能完成句子拆分,又能高效提取指定词性的单词:
步骤1:拆分原DataFrame为句子级别的行
首先我们需要把每行中用感叹号分隔的句子拆出来,同时保证words和tags的对应关系不混乱。这里要注意如果有首尾感叹号或者连续感叹号,拆分后会出现空字符串,得先过滤掉:
import pandas as pd # 假设你的原DataFrame叫df,包含words和tags两列 # 1. 按感叹号拆分句子,同时过滤空句子(注意是中文/英文感叹号,根据实际调整) df['sentence_words'] = df['words'].str.split('!').apply(lambda x: [s.strip() for s in x if s.strip()]) df['sentence_tags'] = df['tags'].str.split('!').apply(lambda x: [s.strip() for s in x if s.strip()]) # 2. 同时展开句子列,得到每行对应一个句子的新DataFrame sentence_df = df.explode(['sentence_words', 'sentence_tags']).reset_index(drop=True)
步骤2:拆分句子为单词-标签对
现在每行是一个完整句子,接下来把每个句子的单词和对应的标签拆分成列表,方便后续提取词性:
# 拆分单词和标签(假设单词/标签之间用空格分隔,根据实际分隔符调整) sentence_df['word_list'] = sentence_df['sentence_words'].str.split() sentence_df['tag_list'] = sentence_df['sentence_tags'].str.split() # 可选:校验单词和标签数量是否匹配,过滤不匹配的行(避免后续出错) sentence_df = sentence_df[sentence_df.apply(lambda x: len(x['word_list']) == len(x['tag_list']), axis=1)]
步骤3:高效提取形容词、名词/动词
这里推荐用分组聚合的方式,比逐行apply效率更高,适合百万级数据:
# 先把每个单词-标签对展开成单独的行 word_tag_df = sentence_df.explode(['word_list', 'tag_list']).rename(columns={ 'word_list': 'word', 'tag_list': 'tag' }) # 定义你的词性标签规则(请根据实际tag体系修改) ADJ_TAGS = {'adj'} # 比如你的形容词标签是'adj' NV_TAGS = {'n', 'v'} # 名词标签'n',动词标签'v' # 聚合提取形容词 adj_agg = word_tag_df[word_tag_df['tag'].isin(ADJ_TAGS)].groupby(level=0)['word'].apply(list) # 聚合提取名词/动词 nv_agg = word_tag_df[word_tag_df['tag'].isin(NV_TAGS)].groupby(level=0)['word'].apply(list) # 合并回句子DataFrame,空值填充为空列表 final_df = sentence_df.join(adj_agg.rename('adjectives')).join(nv_agg.rename('nouns_verbs')) final_df['adjectives'] = final_df['adjectives'].fillna('').apply(lambda x: x if isinstance(x, list) else []) final_df['nouns_verbs'] = final_df['nouns_verbs'].fillna('').apply(lambda x: x if isinstance(x, list) else []) # 可选:保留需要的列,去掉中间辅助列 final_df = final_df[['sentence_words', 'adjectives', 'nouns_verbs']]
优化建议(针对百万级数据)
- 内存优化:如果内存吃紧,可以指定数据类型,比如把
object类型的列换成string类型(Pandas 1.0+支持),减少内存占用:df['words'] = df['words'].astype('string') df['tags'] = df['tags'].astype('string') - 分块处理:如果内存不足以一次性处理,可以用
pd.read_csv的chunksize参数分块读取原数据,逐块处理后再合并结果。 - 并行处理:如果数据量超大,Pandas内存不够,可以用Dask DataFrame,语法和Pandas几乎一致,支持多线程并行处理。
内容的提问来源于stack exchange,提问作者waeiski
相关产品推荐
相关产品推荐

