1. 首页
  2. 令爷课程
  3. 数据探索分析

Python数据分析7步(IMDb Summer Movies Data)

数据:summer_movies | summer_movie_genres

流程

graph LR
    A[1导入库] --> B[2导入数据]
    B --> C[3数据探索与处理]
    C --> D[4数据可视化]
    D --> E[5特征工程]
    E --> F[6模型训练与评估]
    F --> G[7预测新数据]

数据集说明

以下是两个数据文件的详细说明:

文件1:summer_movies.csv

数据预览:

tconst title_type primary_title original_title year runtime_minutes genres simple_title average_rating num_votes
tt0011462 movie Midsummer Madness Midsummer Madness 1920.0 60.0 Drama midsummer madness 7.4 19
tt0026714 movie A Midsummer Night's Dream A Midsummer Night's Dream 1935.0 133.0 Comedy,Fantasy,Romance a midsummer nights dream 6.8 3931
tt0033864 movie The Teachers on Summer Vacation Magistrarna på sommarlov 1941.0 86.0 Comedy the teachers on summer vacation 5.5 78
tt0037325 movie Summer Storm Summer Storm 1944.0 106.0 Crime,Drama,Film-Noir summer storm 6.6 688
tt0038406 movie Centennial Summer Centennial Summer 1946.0 102.0 History,Music,Romance centennial summer 6.1 431

列名及解释:

  • tconst: 电影的唯一标识符(通常用于与其他数据集关联)。
  • title_type: 电影类型(例如 "movie" 表示电影)。
  • primary_title: 电影的主要标题。
  • original_title: 电影的原始标题(可能与主要标题相同)。
  • year: 电影的上映年份。
  • runtime_minutes: 电影的时长(以分钟为单位)。
  • genres: 电影的类型(多个类型之间用逗号分隔)。
  • simple_title: 电影标题的简化版本(用于便于处理或查找)。
  • average_rating: 电影的平均评分。
  • num_votes: 给电影评分的总人数。

文件2:summer_movie_genres.csv

数据预览:

tconst genres
tt0011462 Drama
tt0026714 Comedy
tt0026714 Fantasy
tt0026714 Romance
tt0033864 Comedy

列名及解释:

  • tconst: 电影的唯一标识符(与summer_movies.csv中的tconst对应,用于关联电影类型与其他电影信息)。
  • genres: 电影的单一类型(每一行仅表示一个类型,如果电影属于多个类型,则会有多行数据)。

总结

  • summer_movies.csv: 包含电影的详细信息,如标题、上映年份、时长、评分等。
  • summer_movie_genres.csv: 包含电影的类型信息,每个类型占一行,适合与主数据集进行合并。

这些数据可以通过tconst字段进行关联,以便进一步的分析和处理。

7步分析法

第1步:导入库

首先,我们需要导入必要的Python库,如pandasmatplotlibscikit-learn等。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

第2步:导入数据

然后,我们导入您提供的两个CSV文件。

movies = pd.read_csv('data/IMDb Summer Movies Data/summer_movies.csv')
genres = pd.read_csv('data/IMDb Summer Movies Data/summer_movie_genres.csv')

# 查看前几行数据
print(movies.head())
print(genres.head())
      tconst title_type                    primary_title  \
0  tt0011462      movie                Midsummer Madness   
1  tt0026714      movie        A Midsummer Night's Dream   
2  tt0033864      movie  The Teachers on Summer Vacation   
3  tt0037325      movie                     Summer Storm   
4  tt0038406      movie                Centennial Summer   

              original_title    year  runtime_minutes                  genres  \
0          Midsummer Madness  1920.0             60.0                   Drama   
1  A Midsummer Night's Dream  1935.0            133.0  Comedy,Fantasy,Romance   
2   Magistrarna på sommarlov  1941.0             86.0                  Comedy   
3               Summer Storm  1944.0            106.0   Crime,Drama,Film-Noir   
4          Centennial Summer  1946.0            102.0   History,Music,Romance   

                      simple_title  average_rating  num_votes  
0                midsummer madness             7.4         19  
1         a midsummer nights dream             6.8       3931  
2  the teachers on summer vacation             5.5         78  
3                     summer storm             6.6        688  
4                centennial summer             6.1        431  
      tconst   genres
0  tt0011462    Drama
1  tt0026714   Comedy
2  tt0026714  Fantasy
3  tt0026714  Romance
4  tt0033864   Comedy

第3步:数据探索与处理

在这一步中,进行数据的初步探索,包括检查缺失值、数据类型、合并两个数据集等操作。

# 处理缺失值(如有)
movies = movies.dropna()

# 合并数据集并去掉重复的列
genres_unique = genres.drop_duplicates()
merged_data = pd.merge(movies, genres_unique, on='tconst', how='inner')
merged_data = merged_data.rename(columns={'genres_x': 'genres'}).drop(columns=['genres_y'])

# 如果存在多类型电影,合并类型为字符串
merged_data = merged_data.groupby(['tconst', 'primary_title', 'year', 'runtime_minutes', 'average_rating', 'num_votes'])['genres'].apply(lambda x: ','.join(set(x))).reset_index()

# 检查数据结构
print(merged_data.head())
      tconst                    primary_title    year  runtime_minutes  \
0  tt0011462                Midsummer Madness  1920.0             60.0   
1  tt0026714        A Midsummer Night's Dream  1935.0            133.0   
2  tt0033864  The Teachers on Summer Vacation  1941.0             86.0   
3  tt0037325                     Summer Storm  1944.0            106.0   
4  tt0038406                Centennial Summer  1946.0            102.0   

   average_rating  num_votes                  genres  
0             7.4         19                   Drama  
1             6.8       3931  Comedy,Fantasy,Romance  
2             5.5         78                  Comedy  
3             6.6        688   Crime,Drama,Film-Noir  
4             6.1        431   History,Music,Romance  

第4步:数据可视化

通过可视化来进一步理解数据,比如不同类型电影的平均评分和平均时长。

plt.rcParams['font.family'] = 'Noto Sans CJK SC'
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 1. 不同类型电影的平均评分 (仅显示前十条)
plt.figure(figsize=(10, 6))
top_10_genres = merged_data.groupby('genres')['average_rating'].mean().sort_values(ascending=False).head(10)
sns.barplot(x=top_10_genres.index, y=top_10_genres.values, errorbar=None)
plt.title('前十类型的平均评分')
plt.xlabel('类型')
plt.ylabel('平均评分')
plt.xticks(rotation=45)
plt.show()

# 2. 不同年份的电影数量
plt.figure(figsize=(10, 6))
sns.histplot(data=merged_data, x='year', bins=30)
plt.title('Number of Movies by Year')
plt.xlabel('Year')
plt.ylabel('Number of Movies')
plt.show()

# 3. 电影时长的分布
plt.figure(figsize=(10, 6))
sns.histplot(data=merged_data, x='runtime_minutes', bins=30, kde=True)
plt.title('Distribution of Movie Runtimes')
plt.xlabel('Runtime (minutes)')
plt.ylabel('Frequency')
plt.show()

# 4. 电影评分与票数的关系
plt.figure(figsize=(10, 6))
sns.scatterplot(x='num_votes', y='average_rating', data=merged_data)
plt.title('Relationship between Number of Votes and Average Rating')
plt.xlabel('Number of Votes')
plt.ylabel('Average Rating')
plt.show()

# 5. 每种类型电影的平均时长 (仅显示前十条)
plt.figure(figsize=(10, 6))
top_10_runtime_genres = merged_data.groupby('genres')['runtime_minutes'].mean().sort_values(ascending=False).head(10)
sns.barplot(x=top_10_runtime_genres.index, y=top_10_runtime_genres.values, errorbar=None)
plt.title('前十类型的平均时长')
plt.xlabel('类型')
plt.ylabel('平均时长 (分钟)')
plt.xticks(rotation=45)
plt.show()

# 6. 各类型电影的数量分布 (仅显示前十条)
plt.figure(figsize=(10, 6))
top_10_count_genres = merged_data['genres'].value_counts().head(10)
sns.barplot(x=top_10_count_genres.index, y=top_10_count_genres.values, errorbar=None)
plt.title('前十类型的电影数量')
plt.xlabel('类型')
plt.ylabel('电影数量')
plt.xticks(rotation=45)
plt.show()

# 7. 不同评分区间的电影数量
plt.figure(figsize=(10, 6))
sns.histplot(data=merged_data, x='average_rating', bins=20)
plt.title('Distribution of Average Ratings')
plt.xlabel('Average Rating')
plt.ylabel('Number of Movies')
plt.show()

Python数据分析7步(IMDb Summer Movies Data)

第5步:特征工程

特征工程包括对分类变量进行编码,以及准备模型训练所需的特征和目标变量。

# 将 genres 转换为数值变量(多标签二值化)
genre_dummies = merged_data['genres'].str.get_dummies(sep=',')
merged_data = pd.concat([merged_data, genre_dummies], axis=1)

# 删除重复的列
merged_data = merged_data.loc[:, ~merged_data.columns.duplicated()]

# 显示新的数据集信息
print("特征工程后的数据集列名:", merged_data.columns.tolist())
print("特征工程后的数据集前几行:")
print(merged_data.head())

# 选择特征和目标变量
X = merged_data.drop(['tconst', 'primary_title', 'genres', 'average_rating'], axis=1)
y = merged_data['average_rating']

# 输出数据集形状和列信息
print("特征矩阵 X 的形状:", X.shape)
print("目标变量 y 的形状:", y.shape)
特征工程后的数据集列名: ['tconst', 'primary_title', 'year', 'runtime_minutes', 'average_rating', 'num_votes', 'genres', 'Action', 'Adventure', 'Animation', 'Biography', 'Comedy', 'Crime', 'Documentary', 'Drama', 'Family', 'Fantasy', 'Film-Noir', 'History', 'Horror', 'Music', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Short', 'Sport', 'Talk-Show', 'Thriller', 'War', 'Western']
特征工程后的数据集前几行:
      tconst                    primary_title    year  runtime_minutes  \
0  tt0011462                Midsummer Madness  1920.0             60.0   
1  tt0026714        A Midsummer Night's Dream  1935.0            133.0   
2  tt0033864  The Teachers on Summer Vacation  1941.0             86.0   
3  tt0037325                     Summer Storm  1944.0            106.0   
4  tt0038406                Centennial Summer  1946.0            102.0   

   average_rating  num_votes                  genres  Action  Adventure  \
0             7.4         19                   Drama       0          0   
1             6.8       3931  Comedy,Fantasy,Romance       0          0   
2             5.5         78                  Comedy       0          0   
3             6.6        688   Crime,Drama,Film-Noir       0          0   
4             6.1        431   History,Music,Romance       0          0   

   Animation  ...  Musical  Mystery  Romance  Sci-Fi  Short  Sport  Talk-Show  \
0          0  ...        0        0        0       0      0      0          0   
1          0  ...        0        0        1       0      0      0          0   
2          0  ...        0        0        0       0      0      0          0   
3          0  ...        0        0        0       0      0      0          0   
4          0  ...        0        0        1       0      0      0          0   

   Thriller  War  Western  
0         0    0        0  
1         0    0        0  
2         0    0        0  
3         0    0        0  
4         0    0        0  

[5 rows x 31 columns]
特征矩阵 X 的形状: (837, 27)
目标变量 y 的形状: (837,)

第6步:模型训练与评估

选择一个回归模型进行训练,并评估模型性能。

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练随机森林回归模型
model = RandomForestRegressor()
model.fit(X_train, y_train)

# 预测并评估模型
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)

# 输出评估结果 (中文)
print(f"模型的均方误差 (MSE): {mse:.2f}")
print(f"模型的 R^2 评分: {model.score(X_test, y_test):.2f}")
print(X.columns)
模型的均方误差 (MSE): 1.37
模型的 R^2 评分: 0.10
Index(['year', 'runtime_minutes', 'num_votes', 'Action', 'Adventure',
       'Animation', 'Biography', 'Comedy', 'Crime', 'Documentary', 'Drama',
       'Family', 'Fantasy', 'Film-Noir', 'History', 'Horror', 'Music',
       'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Short', 'Sport',
       'Talk-Show', 'Thriller', 'War', 'Western'],
      dtype='object')

第7步:预测新数据

最后,我们可以使用训练好的模型来预测新的电影数据。

# 假设 X 是训练数据集的 DataFrame,并且包含了所有需要的特征
# 确保 new_movie 字典包含所有特征,并且顺序与 X.columns 一致
new_movie = {
    'year': 2024,  # 年份
    'runtime_minutes': 120,  # 电影时长(分钟)
    'num_votes': 1500,  # 投票数量
    'Action': 0,  # 动作片
    'Adventure': 0,  # 冒险片
    'Animation': 0,  # 动画片
    'Biography': 0,  # 传记片
    'Comedy': 0,  # 喜剧片
    'Crime': 0,  # 犯罪片
    'Documentary': 0,  # 纪录片
    'Drama': 1,  # 剧情片
    'Family': 0,  # 家庭片
    'Fantasy': 0,  # 奇幻片
    'Film-Noir': 0,  # 黑色电影
    'History': 0,  # 历史片
    'Horror': 0,  # 恐怖片
    'Music': 0,  # 音乐片
    'Musical': 0,  # 音乐剧
    'Mystery': 0,  # 悬疑片
    'Romance': 0,  # 爱情片
    'Sci-Fi': 0,  # 科幻片
    'Short': 0,  # 短片
    'Sport': 0,  # 体育片
    'Talk-Show': 0,  # 脱口秀
    'Thriller': 0,  # 惊悚片
    'War': 0,  # 战争片
    'Western': 0  # 西部片
}

# 创建新的 DataFrame,确保列的顺序与 X.columns 一致
new_movie_df = pd.DataFrame([new_movie], columns=X.columns)

# 预测新数据的评分
predicted_rating = model.predict(new_movie_df)
print(f'预测的平均评分为: {predicted_rating[0]:.2f}')
预测的平均评分为: 6.04

原创文章,作者:曾确令,如若转载,请注明出处:https://www.zengqueling.com/psjfxbismd/

联系我们

15602395067

在线咨询:点击这里给我发消息

邮件:eden7@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code