本文目录导读:

我来详细介绍Python进行数据情感分析的完整流程。
环境准备
# 安装必要的库 pip install pandas numpy nltk textblob transformers matplotlib seaborn # 或使用更全面的 pip install scikit-learn jieba snownlp
基础情感分析方法
使用TextBlob(适合英文)
from textblob import TextBlob
import pandas as pd
def analyze_sentiment_textblob(text):
"""使用TextBlob进行情感分析"""
blob = TextBlob(text)
polarity = blob.sentiment.polarity # 情感极性 [-1, 1]
subjectivity = blob.sentiment.subjectivity # 主观性 [0, 1]
# 分类
if polarity > 0.1:
sentiment = '正面'
elif polarity < -0.1:
sentiment = '负面'
else:
sentiment = '中性'
return {
'text': text,
'polarity': polarity,
'subjectivity': subjectivity,
'sentiment': sentiment
}
# 示例
texts = [
"I love this product! It's amazing!",
"This is terrible, worst experience ever.",
"It's okay, nothing special."
]
for text in texts:
result = analyze_sentiment_textblob(text)
print(f"文本: {result['text']}")
print(f"情感: {result['sentiment']}, 极性: {result['polarity']:.2f}")
print("-" * 50)
使用VADER(适合社交媒体文本)
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
analyzer = SentimentIntensityAnalyzer()
def analyze_sentiment_vader(text):
"""使用VADER进行情感分析"""
scores = analyzer.polarity_scores(text)
# 基于compound分数判断
if scores['compound'] >= 0.05:
sentiment = '正面'
elif scores['compound'] <= -0.05:
sentiment = '负面'
else:
sentiment = '中性'
return {
'text': text,
'scores': scores,
'sentiment': sentiment
}
# 示例
text = "This product is really amazing and wonderful!!! But the delivery was slow."
result = analyze_sentiment_vader(text)
print(f"文本: {result['text']}")
print(f"情感分数: {result['scores']}")
print(f"情感: {result['sentiment']}")
使用SnowNLP(适合中文)
from snownlp import SnowNLP
def analyze_sentiment_chinese(text):
"""使用SnowNLP进行中文情感分析"""
s = SnowNLP(text)
sentiment_score = s.sentiments # 0-1之间的分数
if sentiment_score > 0.6:
sentiment = '正面'
elif sentiment_score < 0.4:
sentiment = '负面'
else:
sentiment = '中性'
return {
'text': text,
'score': sentiment_score,
'sentiment': sentiment
}
# 示例
chinese_texts = [
"这个产品太好了,我非常喜欢!",
"质量很差,不建议购买。",
"一般般吧,没什么特别的感觉。"
]
for text in chinese_texts:
result = analyze_sentiment_chinese(text)
print(f"文本: {result['text']}")
print(f"情感: {result['sentiment']}, 分数: {result['score']:.3f}")
print("-" * 30)
使用深度学习模型(BERT)
from transformers import pipeline
# 加载预训练的情感分析模型
sentiment_analyzer = pipeline("sentiment-analysis")
def analyze_sentiment_bert(texts):
"""使用BERT模型进行情感分析"""
results = sentiment_analyzer(texts)
for text, result in zip(texts, results):
print(f"文本: {text}")
print(f"情感: {result['label']}, 置信度: {result['score']:.3f}")
print("-" * 50)
# 示例
texts = [
"I absolutely love this product! Best purchase ever.",
"This is the worst customer service I've ever experienced.",
"The product is good but the price is too high."
]
analyze_sentiment_bert(texts)
批量处理CSV数据
import pandas as pd
from tqdm import tqdm
def batch_sentiment_analysis(input_file, output_file, text_column='text'):
"""批量处理CSV文件中的情感分析"""
# 读取数据
df = pd.read_csv(input_file)
# 初始化分析器
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
analyzer = SentimentIntensityAnalyzer()
# 批量处理
sentiments = []
scores = []
for text in tqdm(df[text_column], desc="分析进度"):
result = analyzer.polarity_scores(str(text))
scores.append(result['compound'])
if result['compound'] >= 0.05:
sentiments.append('正面')
elif result['compound'] <= -0.05:
sentiments.append('负面')
else:
sentiments.append('中性')
# 添加结果到DataFrame
df['sentiment_score'] = scores
df['sentiment'] = sentiments
# 保存结果
df.to_csv(output_file, index=False)
print(f"分析完成!结果已保存到 {output_file}")
# 统计信息
print("\n情感分布:")
print(df['sentiment'].value_counts())
# 使用示例
# batch_sentiment_analysis('reviews.csv', 'reviews_with_sentiment.csv')
可视化分析结果
import matplotlib.pyplot as plt
import seaborn as sns
from wordcloud import WordCloud
def visualize_sentiment_results(results_df):
"""可视化情感分析结果"""
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
# 1. 情感分布饼图
axes[0, 0].pie(results_df['sentiment'].value_counts(),
labels=results_df['sentiment'].value_counts().index,
autopct='%1.1f%%',
colors=['#2ecc71', '#e74c3c', '#f39c12'])
axes[0, 0].set_title('情感分布')
# 2. 情感分数分布直方图
axes[0, 1].hist(results_df['sentiment_score'], bins=30,
color='skyblue', edgecolor='black')
axes[0, 1].set_xlabel('情感分数')
axes[0, 1].set_ylabel('频数')
axes[0, 1].set_title('情感分数分布')
axes[0, 1].axvline(x=0, color='red', linestyle='--', alpha=0.5)
# 3. 箱线图
results_df.boxplot(column='sentiment_score', by='sentiment', ax=axes[1, 0])
axes[1, 0].set_title('各情感类别的分数分布')
axes[1, 0].set_xlabel('情感类别')
axes[1, 0].set_ylabel('情感分数')
# 4. 词云(正面和负面)
positive_text = ' '.join(results_df[results_df['sentiment'] == '正面']['text'])
negative_text = ' '.join(results_df[results_df['sentiment'] == '负面']['text'])
wordcloud_pos = WordCloud(width=400, height=200,
background_color='white').generate(positive_text[:1000])
wordcloud_neg = WordCloud(width=400, height=200,
background_color='white').generate(negative_text[:1000])
axes[1, 1].imshow(wordcloud_pos, interpolation='bilinear')
axes[1, 1].set_title('正面评论词云')
axes[1, 1].axis('off')
plt.tight_layout()
plt.show()
# 示例数据
import pandas as pd
sample_data = pd.DataFrame({
'text': [
"Excellent product!", "Terrible service", "It's okay",
"Love it!", "Hate it", "Not bad",
"Amazing quality", "Very disappointed", "Average"
],
'sentiment': ['正面', '负面', '中性', '正面', '负面', '中性', '正面', '负面', '中性'],
'sentiment_score': [0.8, -0.7, 0.1, 0.9, -0.8, 0.0, 0.85, -0.75, 0.05]
})
visualize_sentiment_results(sample_data)
完整实战示例
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
class SentimentAnalyzer:
def __init__(self):
self.vectorizer = TfidfVectorizer(max_features=5000, ngram_range=(1,2))
self.classifier = MultinomialNB()
self.is_trained = False
def load_and_preprocess_data(self, file_path):
"""加载和预处理数据"""
df = pd.read_csv(file_path)
# 清洗文本
df['text'] = df['text'].str.lower()
df['text'] = df['text'].str.replace('[^a-zA-Z0-9\s]', '')
return df
def train(self, X_train, y_train):
"""训练模型"""
# 特征提取
X_train_tfidf = self.vectorizer.fit_transform(X_train)
# 训练分类器
self.classifier.fit(X_train_tfidf, y_train)
self.is_trained = True
print("模型训练完成!")
def predict(self, texts):
"""预测新的文本"""
if not self.is_trained:
raise ValueError("请先训练模型!")
X_tfidf = self.vectorizer.transform(texts)
predictions = self.classifier.predict(X_tfidf)
probabilities = self.classifier.predict_proba(X_tfidf)
return predictions, probabilities
def evaluate(self, X_test, y_test):
"""评估模型"""
predictions = self.predict(X_test)[0]
print("分类报告:")
print(classification_report(y_test, predictions))
# 混淆矩阵
cm = confusion_matrix(y_test, predictions)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.title('混淆矩阵')
plt.xlabel('预测标签')
plt.ylabel('真实标签')
plt.show()
# 使用示例
if __name__ == "__main__":
# 创建样本数据
sample_texts = [
"I love this movie it is amazing",
"This is terrible I hate it",
"The product quality is excellent",
"Worst experience ever very disappointed",
"Average product nothing special",
"Absolutely fantastic love it",
"Not good not bad just okay",
"Great service and friendly staff"
]
sample_labels = ['positive', 'negative', 'positive', 'negative',
'neutral', 'positive', 'neutral', 'positive']
# 拆分数据
X_train, X_test, y_train, y_test = train_test_split(
sample_texts, sample_labels, test_size=0.3, random_state=42
)
# 训练模型
analyzer = SentimentAnalyzer()
analyzer.train(X_train, y_train)
# 评估模型
analyzer.evaluate(X_test, y_test)
# 预测新数据
new_texts = [
"This is wonderful!",
"I am very unhappy with this purchase"
]
predictions, probabilities = analyzer.predict(new_texts)
print("\n新数据预测结果:")
for text, pred, prob in zip(new_texts, predictions, probabilities):
print(f"文本: {text}")
print(f"预测: {pred} (置信度: {max(prob):.3f})")
print("-" * 40)
最佳实践建议
数据预处理
def preprocess_text(text):
"""文本预处理函数"""
import re
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
# 转换为小写
text = text.lower()
# 移除特殊字符
text = re.sub(r'[^a-zA-Z\s]', '', text)
# 移除停用词
stop_words = set(stopwords.words('english'))
words = text.split()
words = [w for w in words if w not in stop_words]
# 词形还原
lemmatizer = WordNetLemmatizer()
words = [lemmatizer.lemmatize(w) for w in words]
return ' '.join(words)
模型选择建议
- 英文简单文本: VADER 或 TextBlob
- 中文文本: SnowNLP 或 BERT
- 高精度需求: 使用预训练的BERT模型
- 大规模数据: 使用TF-IDF + 机器学习模型
这些方法覆盖了从简单到复杂的情感分析需求,可以根据具体场景选择合适的方案。