4、数据预处理实战:数据清洗、文本分词、停用词过滤

说实话,很多做舆情分析的朋友,一上来就急着跑模型、画热力图。结果呢?数据里一堆垃圾,出来的图根本没法看。我踩过这个坑,所以今天咱们老老实实把数据预处理这块啃下来。

数据预处理,说白了就是给原始数据「洗澡」。洗得干净,后面的分析才靠谱。咱们分三步走:清洗、分词、过滤停用词。

4.1 数据清洗:去重、去噪、处理缺失值

原始数据长什么样?我举个例子你就明白了。从微博、论坛扒下来的评论,经常是这种画风:

# 原始数据样例
"这个产品太棒了!!!"
"这个产品太棒了!!!"  # 重复
"点击链接"  # 广告噪音
"😊😊😊😊😊"  # 纯表情
"   "  # 空白
"我觉的很好"  # 错别字

嗯,看着就头疼。咱们一个一个解决。

4.1.1 去重

重复数据是最常见的。用户刷屏、爬虫重复抓取,都会导致重复。我个人习惯用 pandasdrop_duplicates(),简单粗暴:

import pandas as pd

df = pd.read_csv('weibo_comments.csv')
print(f"去重前数据量: {len(df)}")

# 基于文本内容去重
df_clean = df.drop_duplicates(subset=['content'])
print(f"去重后数据量: {len(df_clean)}")

我在项目中遇到过一种情况:两条评论内容一模一样,但发布时间不同。这时候要不要去重?我的建议是——看场景。如果是做情绪趋势分析,保留时间戳,只去重内容;如果是做词频统计,直接全量去重就行。

4.1.2 去噪

去噪是门手艺活。常见的噪音包括:

  • HTML标签:比如 <br><a> 这些
  • URL链接:http、https 开头的
  • 特殊符号:@某人、#话题#、表情符号
  • 纯数字或纯标点:比如 "123456"、"!!!"

我一般用正则表达式来处理:

import re

def clean_text(text):
    # 去除HTML标签
    text = re.sub(r'<[^>]+>', '', text)
    # 去除URL
    text = re.sub(r'http\S+|www\S+', '', text)
    # 去除@和#内容
    text = re.sub(r'@\w+|#\w+#', '', text)
    # 保留中英文、数字、基本标点
    text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9,。!?、]', '', text)
    return text.strip()

df_clean['content'] = df_clean['content'].apply(clean_text)
注意:正则表达式不要写得太狠。我曾经一激动把中文标点全删了,结果分词全乱了。保留逗号、句号、感叹号这些,对情绪分析有帮助。

4.1.3 处理缺失值

缺失值怎么处理?三种策略:

策略 适用场景 代码示例
直接删除 缺失比例 < 5% df.dropna(subset=['content'])
填充默认值 缺失比例 5%-20% df.fillna({'content': '无内容'})
模型预测填充 缺失比例 > 20% 用其他字段预测(不常用)

我个人习惯:先看看缺失值长什么样。如果是整行空白,直接删;如果是部分字段缺失,看情况填充。别一上来就全删,数据来之不易啊。

4.2 文本分词:jieba vs NLTK

分词是中文NLP的第一步。英文有空格天然分隔,中文可没有。你想想看,「武汉市长江大桥」该怎么切?

  • 武汉 / 市长江 / 大桥 ❌
  • 武汉市 / 长江大桥 ✅

这就是分词的难点。咱们用 jieba 来处理中文,用 NLTK 处理英文(如果有的话)。

4.2.1 jieba 分词实战

import jieba

text = "这个产品真的太棒了,我强烈推荐给所有人!"

# 精确模式(推荐)
words = jieba.lcut(text)
print(words)
# 输出: ['这个', '产品', '真的', '太棒了', ',', '我', '强烈推荐', '给', '所有人', '!']

# 添加自定义词典
jieba.add_word('太棒了')
jieba.add_word('强烈推荐')

# 去掉标点符号
words_clean = [w for w in words if w not in ',。!?、']
print(words_clean)
小技巧:做舆情分析时,建议把品牌名、产品名、竞品名加到自定义词典里。比如「蓝海资料掘金营」这种词,jieba 默认会切成「蓝海 / 资料 / 掘金 / 营」,加了词典才能正确识别。

4.2.2 NLTK 分词(处理英文)

如果你的数据里混了英文,可以用 NLTK:

import nltk
from nltk.tokenize import word_tokenize

text_en = "This product is amazing! I highly recommend it."
tokens = word_tokenize(text_en)
print(tokens)
# 输出: ['This', 'product', 'is', 'amazing', '!', 'I', 'highly', 'recommend', 'it', '.']

嗯,英文分词简单多了。但要注意大小写统一,一般转小写处理。

4.3 停用词过滤

停用词是什么?就是那些高频但没实际意义的词。比如「的」「了」「是」「在」「我」「你」等等。这些词在情绪分析里是噪音,得去掉。

我一般用现成的停用词表,再根据项目情况手动补充。网上有哈工大停用词表、百度停用词表,都挺好用。

# 加载停用词表
def load_stopwords(filepath='stopwords.txt'):
    with open(filepath, 'r', encoding='utf-8') as f:
        stopwords = set([line.strip() for line in f])
    return stopwords

stopwords = load_stopwords()

# 过滤停用词
def filter_stopwords(words, stopwords):
    return [w for w in words if w not in stopwords and len(w) > 1]

# 完整流程
text = "这个产品真的太棒了,我强烈推荐给所有人!"
words = jieba.lcut(text)
words_clean = [w for w in words if w not in ',。!?、']
words_filtered = filter_stopwords(words_clean, stopwords)
print(words_filtered)
# 输出: ['产品', '太棒了', '强烈推荐', '所有人']
核心要点:停用词过滤后,文本从「这个产品真的太棒了,我强烈推荐给所有人!」变成了「产品 太棒了 强烈推荐 所有人」。信息密度大幅提升,情绪关键词一目了然。

4.4 本章知识体系

下面这张图,是我梳理的数据预处理全流程。你跟着走一遍,基本不会出大问题。

数据预处理核心流程 原始数据 数据清洗 去重 · 去噪 · 缺失值 文本分词 jieba / NLTK 过滤 数据清洗详解 去重:drop_duplicates() 去噪:正则表达式 缺失值:dropna/fillna 分词详解 jieba.lcut() 精确模式 自定义词典 add_word() NLTK word_tokenize() 输出:干净的分词结果

4.5 避坑指南

最后,分享几个我踩过的坑:

  • 分词粒度问题:太细了丢失语义,太粗了信息不够。我一般先用精确模式,再根据结果调整词典。
  • 停用词表别乱用:通用停用词表可能把「不」「没」这种否定词也删了。情绪分析里,「不好」「不喜欢」可是关键信息。建议保留否定词。
  • 编码问题:中文数据经常遇到 UnicodeDecodeError。我习惯用 encoding='utf-8',遇到特殊字符加 errors='ignore'
  • 性能问题:几十万条数据分词,jieba 会有点慢。可以试试 jieba.enable_parallel() 开启并行,或者用 pkuseg 替代。
我的习惯:每次预处理完,我都会随机抽 100 条数据人工检查。看看分词对不对、停用词有没有误删。这一步花不了几分钟,但能避免后面整个分析跑偏。

好了,数据预处理这块就讲到这里。你跟着代码走一遍,把原始数据洗得干干净净,后面做热力图就顺手多了。

专注资料整理