基于豆瓣top250电影简介和类型的电影分类

基于豆瓣top250电影简介和类型的电影分类

在这篇博客中,我们将探讨一个数据科学项目,该项目旨在根据电影的简介和类型对电影进行分类。我们将使用Python的Pandas库进行数据操作,并使用Matplotlib库进行数据可视化。这个项目可以帮助我们更好地了解不同类型电影的分布情况,并为不同观众推荐合适的电影。

项目背景

我们从一个包含电影信息的CSV文件入手,文件名为豆瓣.csv。该文件包含电影的名称、简介和类型等信息。我们的目标是根据电影的简介和类型,将电影分类为适合家庭观影、适合年轻人、适合成年观众等多个类别。

项目步骤
  1. 读取CSV文件
  2. 定义分类函数
  3. 应用分类函数
  4. 分类统计
  5. 绘制饼图
  6. 生成电影列表
步骤详解
1. 读取CSV文件

首先,我们使用Pandas库读取CSV文件,并将数据存储在一个DataFrame中。

import pandas as pd

# 读取CSV文件
df = pd.read_csv('豆瓣.csv')
2. 定义分类函数

我们定义一个函数classify_movie,该函数根据电影的简介和类型进行分类。我们定义了一些关键字,函数会检查简介和类型中是否包含这些关键字,从而将电影归类到不同的类别。

def classify_movie(row):
    intro = row['简介']
    types = row['类型']
    all = f"{intro}{types}"
    if isinstance(all, str):
        if any(keyword in all for keyword in ['家庭', '孩子', '温馨', '亲情', '合家欢', '友情', '传统', '伦理', '照顾', '家园', '父母', '兄弟姐妹', '家庭团聚', '爱心', '和谐', '保护', '抚养', '家庭责任', '团结', '亲密', '家庭传统']):
            return '适合家庭观影'
        elif any(keyword in all for keyword in ['青春', '爱情', '活力', '校园', '浪漫', '冒险', '励志', '梦想', '运动', '热血', '成长', '挑战', '同学', '友情', '独立', '自由', '激情', '音乐', '派对', '自我发现', '旅行', '青春困惑', '事业', '奋斗']):
            return '适合年轻人'
        elif any(keyword in all for keyword in ['深刻', '历史', '复杂', '政治', '犯罪', '悬疑', '惊悚', '战争', '社会', '心理', '人性', '暴力', '伦理', '辩论', '法律', '道德', '伦理困境', '剧情', '人生', '政治阴谋', '社会问题', '心理学', '犯罪调查', '战争历史', '权力斗争']):
            return '适合成年观众'
        elif any(keyword in all for keyword in ['科幻', '未来', '太空', '外星人', '机器人', '科技', '平行宇宙', '时间旅行', '人工智能', '异形', '末日', '未来战争', '宇宙探险', '克隆', '超能力', '超自然', '纳米技术', '赛博朋克', '量子力学', '虚拟现实', '星际旅行', '银河帝国', '时间悖论', '外太空']):
            return '适合科幻迷'
        elif any(keyword in all for keyword in ['喜剧', '搞笑', '幽默', '讽刺', '搞怪', '滑稽', '轻松', '欢乐', '恶搞', '反差', '荒诞', '讽刺社会', '黑色幽默', '欢乐时光', '喜剧片', '搞笑场景', '喜剧人物', '搞笑对白', '欢乐冒险', '笑声', '喜剧剧情', '滑稽人物', '荒谬情节']):
            return '适合喜剧迷'
        elif any(keyword in all for keyword in ['动画', '卡通', '动漫', '儿童', '幻想', '魔法', '冒险', '奇幻', '超自然', '童话', '传奇', '动物', '幻想世界', '英雄', '动画片', '魔幻冒险', '童年', '童趣', '卡通角色', '动漫角色', '梦幻', '动画奇观', '卡通片', '幻想故事']):
            return '适合动画迷'
        elif any(keyword in all for keyword in ['恐怖', '惊悚', '鬼怪', '血腥', '灵异', '恐惧', '惊骇', '恐怖片', '超自然', '灵异事件', '恐怖怪物', '黑暗', '恐怖杀手', '诡异', '鬼魂', '恐怖故事', '阴森', '恐怖电影', '黑暗力量', '恐怖氛围', '恐怖场景', '恐怖声音', '恐怖角色', '惊悚剧情']):
            return '适合恐怖迷'
        elif any(keyword in all for keyword in ['纪录片', '真实', '纪实', '历史', '社会', '生态', '文化', '科学', '自然', '人文', '探索', '实地', '采访', '深度', '记录', '观察', '紀錄', '纪实报道', '真实事件', '历史文献', '自然世界', '文化探索', '科学发现', '社会研究']):
            return '适合纪录片爱好者'
        elif any(keyword in all for keyword in ['历史', '战争', '古代', '帝国', '文明', '革命', '传奇', '古代故事', '历史事件', '历史人物', '文献', '古代文化', '战争历史', '历史背景', '古代传奇', '古文明']):
            return '适合历史迷'
        elif any(keyword in all for keyword in ['动作', '战斗', '追逐', '武打', '竞技', '爆破', '特技', '冒险', '英雄', '战争', '反派', '拳击', '枪战', '追击', '暴力', '激战', '动作片', '武术', '动作场面', '动作角色']):
            return '适合动作迷'
        elif any(keyword in all for keyword in ['音乐', '演唱', '演奏', '歌舞', '音乐剧', '音乐会', '音乐家', '乐队', '音乐史', '流行音乐', '古典音乐', '音乐作品', '音乐节', '歌曲', '作曲', '音乐表演']):
            return '适合音乐迷'
        elif any(keyword in all for keyword in ['冒险', '探险', '荒野', '挑战', '探索', '冒险故事', '冒险片', '野外', '生存', '冒险旅程', '冒险人物', '神秘', '古迹', '秘境', '探险队']):
            return '适合冒险迷'
        elif any(keyword in all for keyword in ['运动', '比赛', '体育', '竞技', '球类', '奖杯', '运动员', '运动会', '体育精神', '训练', '体育赛事', '比赛场面', '体育历史', '体育英雄', '体育电影', '运动纪录片']):
            return '适合运动迷'
    return '其他'
3. 应用分类函数

我们将分类函数应用于数据框的每一行,并将结果存储在新列分类中。

# 应用分类函数
df['分类'] = df.apply(classify_movie, axis=1)
4. 分类统计

统计每个分类的数量,并存储在变量category_counts中。

# 分类统计
category_counts = df['分类'].value_counts()
5. 绘制饼图

使用Matplotlib库绘制一个改进后的饼图,显示各分类的分布情况。

import matplotlib.pyplot as plt
import numpy as np

# 绘制改进后的饼图
plt.figure(figsize=(10, 7))
wedges, texts, autotexts = plt.pie(category_counts, labels=category_counts.index, autopct='%1.1f%%', startangle=140)

# 确保饼图是圆形的
plt.axis('equal')

# 设置标题
plt.title('电影分类分布')

# 为每个扇区添加注释
for wedge, label, count in zip(wedges, category_counts.index, category_counts):
    angle = (wedge.theta2 - wedge.theta1) / 2. + wedge.theta1
    x = np.cos(np.deg2rad(angle))
    y = np.sin(np.deg2rad(angle))
    horizontalalignment = {-1: 'right', 1: 'left

'}[int(np.sign(x))]
    connectionstyle = "angle,angleA=0,angleB={}".format(angle)
    plt.annotate(f'{label}: {count}', xy=(x, y), xytext=(1.35*np.sign(x), 1.4*y),
                 horizontalalignment=horizontalalignment, fontsize=10,
                 arrowprops=dict(arrowstyle="->", connectionstyle=connectionstyle))

# 显示图表
plt.show()
6. 生成电影列表

创建一个字典,存储每个分类下的电影列表并为每个电影编号。

# 创建一个字典存储每个类别下的电影列表并编号
category_movies = {}
for category in category_counts.index:
    movies = df[df['分类'] == category]['电影名'].tolist()
    category_movies[category] = {i+1: movie for i, movie in enumerate(movies)}

# 打印每个类别下的电影列表并编号
for category, movies in category_movies.items():
    print(f"\n{category}:")
    for number, movie in movies.items():
        print(f"  {number}. {movie}")

代码详解

导入必要的库

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

这段代码导入了三个库:

  • pandas:用于数据操作和分析。
  • matplotlib.pyplot:用于绘图和数据可视化。
  • numpy:用于数值计算。

读取CSV文件

# 读取CSV文件
df = pd.read_csv('豆瓣.csv')

这行代码使用pandasread_csv函数读取名为豆瓣.csv的CSV文件,并将其存储在df(数据框)变量中。

定义扩展后的分类函数

def classify_movie(row):
    intro = row['简介']
    types = row['类型']
    all = f"{intro}{types}"
    if isinstance(all, str):
        if any(keyword in all for keyword in ['家庭', '孩子', '温馨', '亲情', '合家欢', '友情', '传统', '伦理', '照顾', '家园', '父母', '兄弟姐妹','家庭团聚', '爱心', '和谐', '保护', '抚养', '家庭责任', '团结', '亲密', '家庭传统']):
            return '适合家庭观影'
        elif any(keyword in all for keyword in ['青春', '爱情', '活力', '校园', '浪漫', '冒险', '励志', '梦想', '运动', '热血', '成长', '挑战', '同学', '友情', '独立', '自由', '激情', '音乐', '派对', '自我发现', '旅行', '青春困惑', '事业', '奋斗']):
            return '适合年轻人'
        elif any(keyword in all for keyword in ['深刻', '历史', '复杂', '政治', '犯罪', '悬疑', '惊悚', '战争', '社会', '心理', '人性', '暴力', '伦理', '辩论', '法律', '道德', '伦理困境', '剧情', '人生', '政治阴谋', '社会问题', '心理学', '犯罪调查', '战争历史', '权力斗争']):
            return '适合成年观众'
        elif any(keyword in all for keyword in ['科幻', '未来', '太空', '外星人', '机器人', '科技', '平行宇宙', '时间旅行', '人工智能', '异形', '末日', '未来战争', '宇宙探险', '克隆', '超能力', '超自然', '纳米技术', '赛博朋克', '量子力学', '虚拟现实', '星际旅行', '银河帝国', '时间悖论', '外太空']):
            return '适合科幻迷'
        elif any(keyword in all for keyword in ['喜剧', '搞笑', '幽默', '讽刺', '搞怪', '滑稽', '轻松', '欢乐', '恶搞', '反差', '荒诞', '讽刺社会', '黑色幽默', '欢乐时光', '喜剧片', '搞笑场景', '喜剧人物', '搞笑对白', '欢乐冒险', '笑声', '喜剧剧情', '滑稽人物', '荒谬情节']):
            return '适合喜剧迷'
        elif any(keyword in all for keyword in ['动画', '卡通', '动漫', '儿童', '幻想', '魔法', '冒险', '奇幻', '超自然', '童话', '传奇', '动物', '幻想世界', '英雄', '动画片', '魔幻冒险', '童年', '童趣', '卡通角色', '动漫角色', '梦幻', '动画奇观', '卡通片', '幻想故事']):
            return '适合动画迷'
        elif any(keyword in all for keyword in ['恐怖', '惊悚', '鬼怪', '血腥', '灵异', '恐惧', '惊骇', '恐怖片', '超自然', '灵异事件', '恐怖怪物', '黑暗', '恐怖杀手', '诡异', '鬼魂', '恐怖故事', '阴森', '恐怖电影', '黑暗力量', '恐怖氛围', '恐怖场景', '恐怖声音', '恐怖角色', '惊悚剧情']):
            return '适合恐怖迷'
        elif any(keyword in all for keyword in ['纪录片', '真实', '纪实', '历史', '社会', '生态', '文化', '科学', '自然', '人文', '探索', '实地', '采访', '深度', '记录', '观察', '紀錄', '纪实报道', '真实事件', '历史文献', '自然世界', '文化探索', '科学发现', '社会研究']):
            return '适合纪录片爱好者'
        elif any(keyword in all for keyword in ['历史', '战争', '古代', '帝国', '文明', '革命', '传奇', '古代故事', '历史事件', '历史人物', '文献', '古代文化', '战争历史', '历史背景', '古代传奇', '古文明']):
            return '适合历史迷'
        elif any(keyword in all for keyword in ['动作', '战斗', '追逐', '武打', '竞技', '爆破', '特技', '冒险', '英雄', '战争', '反派', '拳击', '枪战', '追击', '暴力', '激战', '动作片', '武术', '动作场面', '动作角色']):
            return '适合动作迷'
        elif any(keyword in all for keyword in ['音乐', '演唱', '演奏', '歌舞', '音乐剧', '音乐会', '音乐家', '乐队', '音乐史', '流行音乐', '古典音乐', '音乐作品', '音乐节', '歌曲', '作曲', '音乐表演']):
            return '适合音乐迷'
        elif any(keyword in all for keyword in ['冒险', '探险', '荒野', '挑战', '探索', '冒险故事', '冒险片', '野外', '生存', '冒险旅程', '冒险人物', '神秘', '古迹', '秘境', '探险队']):
            return '适合冒险迷'
        elif any(keyword in all for keyword in ['运动', '比赛', '体育', '竞技', '球类', '奖杯', '运动员', '运动会', '体育精神', '训练', '体育赛事', '比赛场面', '体育历史', '体育英雄', '体育电影', '运动纪录片']):
            return '适合运动迷'
    return '其他'

这个函数classify_movie根据电影的简介和类型进行分类。详细说明如下:

  1. 提取电影简介和类型

    intro = row['简介']
    types = row['类型']
    
    • intro:获取当前行的简介内容。
    • types:获取当前行的类型内容。
  2. 合并简介和类型

    all = f"{intro}{types}"
    
    • 将简介和类型合并成一个字符串。
  3. 检查合并字符串是否为字符串类型

    if isinstance(all, str):
    
  4. 根据关键词进行分类

    • 使用if any(keyword in all for keyword in [...])结构,检查合并字符串中是否包含特定关键词。
    • 根据匹配的关键词返回相应的分类标签,如"适合家庭观影"、"适合年轻人"等。
  5. 默认返回"其他"

    return '其他'
    
    • 如果没有匹配到任何关键词,则返回"其他"。

应用分类函数

# 应用分类函数
df['分类'] = df.apply(classify_movie, axis=1)

这行代码将classify_movie函数应用于数据框的每一行,并将结果存储在新列分类中。

分类统计

# 分类统计
category_counts = df['分类'].value_counts()

这行代码统计每个分类的数量,并存储在category_counts变量中。

绘制改进后的饼图

plt.figure(figsize=(10, 7))
wedges, texts, autotexts = plt.pie(category_counts, labels=category_counts.index, autopct='%1.1f%%', startangle=140)

# 确保饼图是圆形的
plt.axis('equal')

# 设置标题
plt.title('电影分类分布')

# 为每个扇区添加注释
for wedge, label, count in zip(wedges, category_counts.index, category_counts):
    angle = (wedge.theta2 - wedge.theta1) / 2. + wedge.theta1


    x = np.cos(np.deg2rad(angle))
    y = np.sin(np.deg2rad(angle))
    horizontalalignment = {-1: 'right', 1: 'left'}[int(np.sign(x))]
    connectionstyle = "angle,angleA=0,angleB={}".format(angle)
    plt.annotate(f'{label}: {count}', xy=(x, y), xytext=(1.35*np.sign(x), 1.4*y),
                 horizontalalignment=horizontalalignment, fontsize=10,
                 arrowprops=dict(arrowstyle="->", connectionstyle=connectionstyle))

# 显示图表
plt.show()

这段代码绘制一个改进后的饼图:

  1. 设置图表大小

    plt.figure(figsize=(10, 7))
    
  2. 绘制饼图

    wedges, texts, autotexts = plt.pie(category_counts, labels=category_counts.index, autopct='%1.1f%%', startangle=140)
    
    • category_counts:每个分类的数量。
    • labels:分类标签。
    • autopct:显示百分比。
    • startangle:起始角度。
  3. 确保饼图是圆形的

    plt.axis('equal')
    
  4. 设置标题

    plt.title('电影分类分布')
    
  5. 为每个扇区添加注释

    for wedge, label, count in zip(wedges, category_counts.index, category_counts):
        angle = (wedge.theta2 - wedge.theta1) / 2. + wedge.theta1
        x = np.cos(np.deg2rad(angle))
        y = np.sin(np.deg2rad(angle))
        horizontalalignment = {-1: 'right', 1: 'left'}[int(np.sign(x))]
        connectionstyle = "angle,angleA=0,angleB={}".format(angle)
        plt.annotate(f'{label}: {count}', xy=(x, y), xytext=(1.35*np.sign(x), 1.4*y),
                     horizontalalignment=horizontalalignment, fontsize=10,
                     arrowprops=dict(arrowstyle="->", connectionstyle=connectionstyle))
    
    • 计算每个扇区的中心角度,用于确定注释的位置。
    • 使用plt.annotate在每个扇区附近添加注释,包括分类标签和数量。
  6. 显示图表

    plt.show()
    

创建一个字典存储每个类别下的电影列表并编号

# 创建一个字典存储每个类别下的电影列表并编号
category_movies = {}
for category in category_counts.index:
    movies = df[df['分类'] == category]['电影名'].tolist()
    category_movies[category] = {i+1: movie for i, movie in enumerate(movies)}

这段代码创建一个字典category_movies,其中每个类别的键对应一个编号的电影列表:

  1. 初始化空字典

    category_movies = {}
    
  2. 遍历每个分类

    for category in category_counts.index:
    
  3. 获取每个分类下的电影列表

    movies = df[df['分类'] == category]['电影名'].tolist()
    
  4. 将电影列表编号并存储在字典中

    category_movies[category] = {i+1: movie for i, movie in enumerate(movies)}
    

打印每个类别下的电影列表并编号

# 打印每个类别下的电影列表并编号
for category, movies in category_movies.items():
    print(f"\n{category}:")
    for number, movie in movies.items():
        print(f"  {number}. {movie}")

这段代码打印每个分类下的电影列表,并为每个电影添加编号:

  1. 遍历每个分类和对应的电影列表

    for category, movies in category_movies.items():
    
  2. 打印分类名称

    print(f"\n{category}:")
    
  3. 打印每个电影的编号和名称

    for number, movie in movies.items():
        print(f"  {number}. {movie}")
    

这段代码主要完成了以下任务:

  1. 从CSV文件读取电影数据。

  2. 根据简介和类型对电影进行分类。

  3. 统计每个分类的数量。

  4. 绘制一个饼图显示分类分布。

  5. 创建一个字典存储每个分类下的电影列表并编号。

  6. 打印每个分类下的电影列表并编号。

    总结

    通过以上步骤,我们成功地对电影进行了分类,并生成了分类统计和可视化图表。这些结果可以帮助我们了解不同类型电影的分布情况,并为不同观众推荐合适的电影。这只是数据科学项目的一个简单示例,通过类似的方法,我们可以对更多的电影数据进行更深入的分析和研究。希望这篇博客对你有所帮助。

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值