豆瓣电影数据分析全解析

部署运行你感兴趣的模型镜像

🎬 豆瓣电影数据分析全解析

本篇博客将带你深入分析豆瓣电影数据,通过可视化图表揭示电影类型分布、演员表现和评分规律!

📊 数据分析概览

在上一篇博客中,我们成功爬取了豆瓣电影数据,现在让我们用数据科学的方法来挖掘这些数据背后的故事!本次分析将涵盖三个核心维度:

  • 🎭 电影类型分析 - 了解豆瓣电影的题材分布
  • 🌟 演员影响力分析 - 找出最活跃的电影演员
  • 评分与星级关系 - 探索用户评价规律
  • 由于我爬取采集的目标数据维度字段很多,本次也就简单分析了6个图表,更多图表各位可以自行那我的爬虫代码或者数据自行拓展分析!!!

🛠️ 技术栈与数据准备

首先导入必要的分析库并设置中文字体:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from collections import Counter
import re
import numpy as np

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

# 读取数据
df = pd.read_csv('豆瓣电影信息.csv')

🎭 电影类型分析

数据处理与统计

def process_types(type_str):
    """处理类型字符串,分割成列表"""
    if pd.isna(type_str):
        return []
    types = [t.strip() for t in str(type_str).split(',')]
    return [t for t in types if t]

# 统计所有类型
all_types = []
for type_str in df['type']:
    all_types.extend(process_types(type_str))

type_counts = Counter(all_types)
type_df = pd.DataFrame(list(type_counts.items()), columns=['类型', '数量'])
type_df = type_df.sort_values('数量', ascending=False)

📈 可视化展示

我们使用双图对比来展示类型分布:

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8))

# 左侧柱状图
bars = ax1.bar(type_df['类型'], type_df['数量'], color=plt.cm.Set3(range(len(type_df))))
ax1.set_title('各类型电影数量分布', fontsize=16, fontweight='bold')
ax1.tick_params(axis='x', rotation=45)

# 右侧饼图
colors = plt.cm.Set3(range(len(type_df)))
wedges, texts, autotexts = ax2.pie(type_df['数量'],
                                  labels=type_df['类型'],
                                  autopct='%1.1f%%',
                                  colors=colors,
                                  startangle=90)

📊 分析结果

通过分析我们发现:

  • 剧情片 🎬 占据绝对主导地位
  • 爱情 ❤️ 和 喜剧 😄 类型紧随其后
  • 平均每部电影包含 2-3个类型标签
    在这里插入图片描述

🌟 演员影响力分析

演员数据提取

def extract_actors(actor_str):
    """提取演员列表,处理各种格式"""
    if pd.isna(actor_str):
        return []
    actors = str(actor_str).split(',')
    return [actor.strip() for actor in actors if actor.strip()]

# 提取所有演员
all_actors = []
for actors_str in df['actors']:
    all_actors.extend(extract_actors(actors_str))

actor_counts = Counter(all_actors)
top_30_actors = actor_counts.most_common(30)

📊 演员排行榜可视化

plt.figure(figsize=(15, 10))
colors = plt.cm.viridis(range(len(top_actors_df)))

bars = plt.barh(top_actors_df['演员'], top_actors_df['参演电影数量'], color=colors)
plt.xlabel('参演电影数量', fontsize=12)
plt.title('参演电影最多的30名演员', fontsize=16, fontweight='bold')
plt.gca().invert_yaxis()  # 反转y轴,使最高的在顶部

🎯 关键发现

  • 某些演员在数据集中出现频率极高 🚀
  • 反映了这些演员的高产程度市场活跃度
  • 为研究演员类型偏好提供了数据支持
    在这里插入图片描述

⭐ 评分与星级深度分析

数据清洗与预处理

# 数据清洗
df = df.drop_duplicates(subset='subject', keep='first')
df['score'] = pd.to_numeric(df['score'], errors='coerce')
df['star'] = pd.to_numeric(df['star'], errors='coerce')
df['comment_count'] = pd.to_numeric(df['comment_count'], errors='coerce')
df = df.dropna(subset=['score', 'star'])

🏆 双榜单对比分析

# 获取评分前10和星级前10的电影
top_10_score = df.nlargest(10, 'score')[['name', 'score', 'star', 'comment_count', 'date']]
top_10_star = df.nlargest(10, ['star', 'score'])[['name', 'star', 'score', 'comment_count', 'date']]

# 创建对比图表
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(22, 12))

📊 多维度数据展示

我们采用双条形图同时展示评分和评论数:

# 左侧:评分前10的电影详细数据
bars1 = ax1.barh(y_pos - bar_width/2, top_10_score['score'], bar_width,
                label='评分', color='#FF6B6B', alpha=0.8)
bars2 = ax1.barh(y_pos + bar_width/2, top_10_score['comment_count']/10000, bar_width,
                label='评论数(万)', color='#4ECDC4', alpha=0.8)

🔍 评分与星级关系探索

通过散点图分析两者相关性:

plt.figure(figsize=(12, 8))
scatter = plt.scatter(df['score'], df['star'], c=colors, s=sizes, alpha=0.6, 
                     edgecolors='black', linewidth=0.5)

# 添加趋势线
z = np.polyfit(df['score'], df['star'], 1)
p = np.poly1d(z)
plt.plot(df['score'], p(df['score']), "r--", alpha=0.8, linewidth=2)

在这里插入图片描述

在这里插入图片描述

💡 核心发现与洞察

🎯 主要结论

  1. 类型分布 📊

    • 剧情片是绝对主流,反映观众对故事性的重视
    • 类型混合现象普遍,单一类型电影较少
  2. 演员生态 🌟

    • 存在明显的"高产演员"群体
    • 演员参演频率分布呈现长尾效应
  3. 评价体系

    • 评分与星级存在正相关关系
    • 高评分电影不一定获得高评论数
    • 存在"叫好不叫座"的现象

📈 数据质量评估

  • 数据完整性良好,缺失值较少 ✅
  • 评分分布合理,符合真实用户行为模式 ✅
  • 类型标签准确度高,便于分析 ✅

🚀 后续分析方向

基于当前分析,可以进一步探索:

  • 🕒 时间趋势分析 - 研究类型和评分的年度变化
  • 🌍 地域分布 - 分析不同地区电影的评分差异
  • 💬 评论情感分析 - 挖掘用户评论的情感倾向
  • 🎯 推荐算法 - 基于类型和评分构建电影推荐系统

💻 完整代码获取

所有分析代码如下完整展示,建议按模块逐步运行,确保理解每个分析步骤的实现逻辑。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from collections import Counter
import re

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

# 读取数据
df = pd.read_csv('豆瓣电影信息.csv')

# 处理类型数据
def process_types(type_str):
    """处理类型字符串,分割成列表"""
    if pd.isna(type_str):
        return []
    # 去除空格并按逗号分割
    types = [t.strip() for t in str(type_str).split(',')]
    return [t for t in types if t]  # 过滤空字符串

# 统计所有类型
all_types = []
for type_str in df['type']:
    all_types.extend(process_types(type_str))

# 统计类型频率
type_counts = Counter(all_types)
type_df = pd.DataFrame(list(type_counts.items()), columns=['类型', '数量'])
type_df = type_df.sort_values('数量', ascending=False)

print("各类型电影数量统计:")
print(type_df)

# 创建图表
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8))

# 左侧柱状图
bars = ax1.bar(type_df['类型'], type_df['数量'], color=plt.cm.Set3(range(len(type_df))))
ax1.set_title('各类型电影数量分布', fontsize=16, fontweight='bold')
ax1.set_xlabel('电影类型', fontsize=12)
ax1.set_ylabel('数量', fontsize=12)
ax1.tick_params(axis='x', rotation=45)

# 在柱状图上添加数值标签
for bar in bars:
    height = bar.get_height()
    ax1.text(bar.get_x() + bar.get_width()/2., height + 0.1,
             f'{int(height)}', ha='center', va='bottom', fontsize=10)

# 右侧饼图
colors = plt.cm.Set3(range(len(type_df)))
wedges, texts, autotexts = ax2.pie(type_df['数量'],
                                  labels=type_df['类型'],
                                  autopct='%1.1f%%',
                                  colors=colors,
                                  startangle=90)

# 美化饼图文本
for autotext in autotexts:
    autotext.set_color('white')
    autotext.set_fontweight('bold')
    autotext.set_fontsize(10)

for text in texts:
    text.set_fontsize(10)

ax2.set_title('各类型电影占比', fontsize=16, fontweight='bold')

# 调整布局
plt.tight_layout()
plt.show()

# 输出详细统计信息
total_movies = len(df)
total_types = len(type_df)
print(f"\n统计摘要:")
print(f"总电影数量: {total_movies}")
print(f"涉及类型总数: {total_types}")
print(f"平均每部电影类型数: {len(all_types)/total_movies:.2f}")

# 显示前5大类型
print(f"\n前5大电影类型:")
for i, row in type_df.head().iterrows():
    percentage = (row['数量'] / len(all_types)) * 100
    print(f"{row['类型']}: {row['数量']}部 ({percentage:.1f}%)")
#%%
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from collections import Counter
import re

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 读取数据
df = pd.read_csv('豆瓣电影信息.csv')

# 处理演员数据
def extract_actors(actor_str):
    """提取演员列表,处理各种格式"""
    if pd.isna(actor_str):
        return []

    # 清理字符串并分割
    actors = str(actor_str).split(',')
    # 去除空格和空值
    actors = [actor.strip() for actor in actors if actor.strip()]
    return actors

# 提取所有演员
all_actors = []
for actors_str in df['actors']:
    all_actors.extend(extract_actors(actors_str))

# 统计演员出现次数
actor_counts = Counter(all_actors)

# 获取前30名演员
top_30_actors = actor_counts.most_common(30)

# 创建数据框
top_actors_df = pd.DataFrame(top_30_actors, columns=['演员', '参演电影数量'])

# 可视化
plt.figure(figsize=(15, 10))
colors = plt.cm.viridis(range(len(top_actors_df)))

# 创建水平条形图
bars = plt.barh(top_actors_df['演员'], top_actors_df['参演电影数量'], color=colors)
plt.xlabel('参演电影数量', fontsize=12)
plt.title('参演电影最多的30名演员', fontsize=16, fontweight='bold')
plt.gca().invert_yaxis()  # 反转y轴,使最高的在顶部

# 在条形上添加数值标签
for i, bar in enumerate(bars):
    width = bar.get_width()
    plt.text(width + 0.1, bar.get_y() + bar.get_height()/2,
             f'{int(width)}', ha='left', va='center', fontsize=10)

plt.tight_layout()
plt.show()

# 打印详细结果
print("参演电影最多的30名演员:")
print("=" * 50)
for i, (actor, count) in enumerate(top_30_actors, 1):
    print(f"{i:2d}. {actor:<15} - {count} 部电影")

# 输出一些统计信息
print(f"\n统计信息:")
print(f"总演员数量: {len(actor_counts)}")
print(f"总电影数量: {len(df)}")
print(f"平均每个演员参演电影数: {len(all_actors)/len(actor_counts):.2f}")
#%%
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 读取数据
df = pd.read_csv('豆瓣电影信息.csv')

# 数据清洗和预处理
# 去除重复的电影条目(基于subject ID)
df = df.drop_duplicates(subset='subject', keep='first')

# 转换数据类型
df['score'] = pd.to_numeric(df['score'], errors='coerce')
df['star'] = pd.to_numeric(df['star'], errors='coerce')
df['comment_count'] = pd.to_numeric(df['comment_count'], errors='coerce')

# 过滤有效数据
df = df.dropna(subset=['score', 'star'])

# 获取评分前10的电影
top_10_score = df.nlargest(10, 'score')[['name', 'score', 'star', 'comment_count', 'date']].reset_index(drop=True)

# 获取星级前10的电影
top_10_star = df.nlargest(10, ['star', 'score'])[['name', 'star', 'score', 'comment_count', 'date']].reset_index(drop=True)

# 创建对比图表
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(22, 12))

# 左侧:评分前10的电影详细数据
y_pos = np.arange(len(top_10_score))
bar_width = 0.35

# 创建评分和评论数的双条形图
bars1 = ax1.barh(y_pos - bar_width/2, top_10_score['score'], bar_width,
                label='评分', color='#FF6B6B', alpha=0.8)
bars2 = ax1.barh(y_pos + bar_width/2, top_10_score['comment_count']/10000, bar_width,
                label='评论数(万)', color='#4ECDC4', alpha=0.8)

ax1.set_yticks(y_pos)
ax1.set_yticklabels([f"{name[:15]}..." if len(name) > 15 else name for name in top_10_score['name']], fontsize=10)
ax1.set_xlabel('数值', fontsize=12, fontweight='bold')
ax1.set_title('评分前10电影详细数据对比', fontsize=16, fontweight='bold', pad=20)
ax1.legend(loc='lower right')
ax1.grid(axis='x', alpha=0.3)

# 添加数据标签
for i, (bar1, bar2) in enumerate(zip(bars1, bars2)):
    # 评分标签
    ax1.text(bar1.get_width() + 0.1, bar1.get_y() + bar1.get_height()/2,
             f'{bar1.get_width():.1f}', ha='left', va='center', fontsize=9, fontweight='bold')
    # 评论数标签
    ax1.text(bar2.get_width() + 0.1, bar2.get_y() + bar2.get_height()/2,
             f'{bar2.get_width():.1f}万', ha='left', va='center', fontsize=9, fontweight='bold')

# 右侧:星级前10的电影详细数据
y_pos2 = np.arange(len(top_10_star))

bars3 = ax2.barh(y_pos2 - bar_width/2, top_10_star['star'], bar_width,
                label='星级', color='#45B7D1', alpha=0.8)
bars4 = ax2.barh(y_pos2 + bar_width/2, top_10_star['comment_count']/10000, bar_width,
                label='评论数(万)', color='#96CEB4', alpha=0.8)

ax2.set_yticks(y_pos2)
ax2.set_yticklabels([f"{name[:15]}..." if len(name) > 15 else name for name in top_10_star['name']], fontsize=10)
ax2.set_xlabel('数值', fontsize=12, fontweight='bold')
ax2.set_title('星级前10电影详细数据对比', fontsize=16, fontweight='bold', pad=20)
ax2.legend(loc='lower right')
ax2.grid(axis='x', alpha=0.3)

# 添加数据标签
for i, (bar3, bar4) in enumerate(zip(bars3, bars4)):
    # 星级标签
    ax2.text(bar3.get_width() + 0.1, bar3.get_y() + bar3.get_height()/2,
             f'{int(bar3.get_width())}星', ha='left', va='center', fontsize=9, fontweight='bold')
    # 评论数标签
    ax2.text(bar4.get_width() + 0.1, bar4.get_y() + bar4.get_height()/2,
             f'{bar4.get_width():.1f}万', ha='left', va='center', fontsize=9, fontweight='bold')

plt.tight_layout()
plt.show()

# 创建详细信息表格
print("=" * 100)
print("评分前10电影完整信息:")
print("=" * 100)
print(f"{'排名':<3} {'电影名称':<25} {'评分':<6} {'星级':<4} {'评论数':<8} {'上映日期'}")
print("-" * 100)
for i, row in top_10_score.iterrows():
    comment_str = f"{row['comment_count']/10000:.1f}万" if row['comment_count'] > 10000 else f"{int(row['comment_count'])}"
    print(f"{i+1:<3} {row['name']:<25} {row['score']:<6.1f} {row['star']:<4} {comment_str:<8} {row['date']}")

print("\n" + "=" * 100)
print("星级前10电影完整信息:")
print("=" * 100)
print(f"{'排名':<3} {'电影名称':<25} {'星级':<4} {'评分':<6} {'评论数':<8} {'上映日期'}")
print("-" * 100)
for i, row in top_10_star.iterrows():
    comment_str = f"{row['comment_count']/10000:.1f}万" if row['comment_count'] > 10000 else f"{int(row['comment_count'])}"
    print(f"{i+1:<3} {row['name']:<25} {row['star']:<4} {row['score']:<6.1f} {comment_str:<8} {row['date']}")

# 创建另一个可视化:评分vs星级的散点图
plt.figure(figsize=(12, 8))

# 为不同类型的数据点设置颜色
colors = []
sizes = []
for _, row in df.iterrows():
    if row['name'] in top_10_score['name'].values and row['name'] in top_10_star['name'].values:
        colors.append('red')  # 同时在两个榜单中的电影
        sizes.append(150)
    elif row['name'] in top_10_score['name'].values:
        colors.append('blue')  # 只在评分榜中的电影
        sizes.append(100)
    elif row['name'] in top_10_star['name'].values:
        colors.append('green')  # 只在星级榜中的电影
        sizes.append(100)
    else:
        colors.append('gray')  # 其他电影
        sizes.append(30)

# 创建散点图
scatter = plt.scatter(df['score'], df['star'], c=colors, s=sizes, alpha=0.6, edgecolors='black', linewidth=0.5)

# 添加趋势线
z = np.polyfit(df['score'], df['star'], 1)
p = np.poly1d(z)
plt.plot(df['score'], p(df['score']), "r--", alpha=0.8, linewidth=2)

plt.xlabel('评分 (Score)', fontsize=12, fontweight='bold')
plt.ylabel('星级 (Star)', fontsize=12, fontweight='bold')
plt.title('电影评分与星级关系散点图', fontsize=16, fontweight='bold')
plt.grid(alpha=0.3)

# 添加图例
from matplotlib.lines import Line2D
legend_elements = [
    Line2D([0], [0], marker='o', color='w', markerfacecolor='red', markersize=8, label='双榜单电影'),
    Line2D([0], [0], marker='o', color='w', markerfacecolor='blue', markersize=8, label='仅评分榜电影'),
    Line2D([0], [0], marker='o', color='w', markerfacecolor='green', markersize=8, label='仅星级榜电影'),
    Line2D([0], [0], marker='o', color='w', markerfacecolor='gray', markersize=8, label='其他电影')
]
plt.legend(handles=legend_elements, loc='upper left')

plt.tight_layout()
plt.show()

# 计算相关性
correlation = df['score'].corr(df['star'])
print(f"\n评分与星级的相关性系数: {correlation:.3f}")

# 分析重叠电影
overlap_movies = set(top_10_score['name']).intersection(set(top_10_star['name']))
print(f"\n同时出现在两个榜单的电影 ({len(overlap_movies)}部):")
for movie in overlap_movies:
    score = top_10_score[top_10_score['name'] == movie]['score'].values[0]
    star = top_10_star[top_10_star['name'] == movie]['star'].values[0]
    print(f"  - {movie} (评分: {score}, 星级: {star})")

通过这次数据分析,我们不仅了解了豆瓣电影的现状,还掌握了用Python进行数据可视化的实用技巧!🎉 希望这篇教程能为你的数据分析之旅提供启发!

Happy Analyzing! 📊✨

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追寻定义的熊百涛!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值