根据IMDB5000部电影数据集进行下列数据分析:
- 数据准备:读取数据并查看数据的基本信息
- 数据清洗:缺失值处理,重复值处理,处理后“干净”数据的基本信息。
- 数据分析及可视化展示:
电影出品国及地区和演员票房的情况分析:
绘制电影出品数量排名前10位的国家及地区的条形图;绘制票房前十的电影中喜爱男 1 号,男 2 号,男 3 号的人数的分组条形图。电影数量的分析:
按年份统计每年电影总数量、彩色影片数量和黑白影片数量并绘制折线图(在同一个坐标系中绘制)。电影类型的分析:
绘制不同类型的电影数量条形图和饼图。电影评分统计及电影评分相关因素分析:
找出评分排名前 20 位电影的片名和评分;绘制所有影片评分与受欢迎程度的关系散点图。
读取数据并查看数据的基本信息
import pandas as pd
import numpy as np
movies = pd.read_csv('D:\\gaojie\\movie_metadata.csv',encoding='utf—8')
打印前五行观察
movies.head (5)
通过前五行,可以看出数据集有28列,以及具体的列名。同时也可以发现,前五行里就有空值较多的行,说明我们需要对数据作处理。
输入 .shape 看看有多少行多少列
movies.shape
可以看到,数据集的维度是5043行,28列。
查看列的数据类型
movies.dtypes
可以看出,数据集中涉及数据的列默认为 float64 和 int64,无需对数据做类型转换。而其他列均为 object 类型,后面需要考虑是否做类型转换。
数据清洗也叫数据预处理,因为大多时候获取的数据并不符合我们的数据分析的标准这时候我们就需要对数据进行预处理,使之数据更加规整有序方便我们下一步的分析。数据清洗通常需要数据分析大部分时间,但是我觉得也是有一定的步骤的,我将它大致分为六部曲: 选择子集→列名重命名→缺失数据处理→数据类型转换→数据排序→异常值处理
先通过isnull函数看一下是否有空值,结果是有空值的地方显示为True,没有的显示为False
print(movies.isnull())
可以看到有空值的行非常之多,在分析之前我们需要处理对行进行取舍。
再通 过 isnull().sum() 直接看每一列有多少空值
print(movies.isnull().sum())
可以看到,只有极少列没有空值,有的列空值异常之多。因此我们处理的时候只能选择让重点的列没有空值,删除行而不要删除列。
为了方便我们这里选择直接删除有缺失值的行
print ('删除缺失值前数据集大小 ',movies.shape )
# how=‘any’ 在给定的任何一列中有缺失值就删除
movies = movies.dropna(how ='any' )
print ('删除缺失值后大小 ',movies.shape )
可以看到一千多行有缺失值的数据被删除掉了,对数据的损耗还是非常大的。最好是只删除重要列有缺失值的行,或者按缺失值的比例删除。规定n行有多少个缺失值时再删除。
这里我们选择删除电影名重复的行:
movies.drop_duplicates(subset=["movie_title"],keep='first',inplace=True)
print(movies.duplicated().value_counts())
先用 duplicated() 方法进行逻辑判断,确定是否有重复值,统计重复值的数量
print(movies.duplicated().value_counts())
可以看到,虽然有众多重复值,但我们应该考虑哪些列的重复值是不允许出现应该删除的。因为很多重复值可能只是数据相同,或者演员、国家这样的重复值是允许出现的。
再用 duplicates(subset,keep,inplace) 方法对某几列下面的重复行删除
这里我们选择删除所有电影名重复的行
movies.drop_duplicates(subset=[‘director_name’],keep='first',inplace=True)
print(movies.duplicated().value_counts())
可以看到重复值并没有变化,因为重复值均为 int64 类型,也就是说没有电影名重复的行。因此没有数据被删除掉 。
使用 info 查看处理后“干净”数据的基本信息:
movies.info
可以看到,处理后数据为3655行,保留了所有的列。我们将在此数据集上做数据分析及可视化展示。
按country分组,统计所有国家的电影数量
country_group = movies.groupby('country').size()
country_group
电影出品数量排名前10位的国家
group_head_10=country_group.sort_values(ascending=False).head(10)
group_head_10
得到了电影数量前十的国家及对应的电影数量,因为电影数量为 int64,因此可以直接作为纵轴数值绘图。
绘制电影出品数量排名前 10 位的柱形图的国家及地区的条形图
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['font.family']='SimHei'
plt.ylabel('电影数量')
plt.title('电影出品数量排名前10位的国家及地区的条形图')
group_head_10.plot(kind = 'bar')
将电影按票房数降序排序,切取前10的电影信息
movies_max=movies.sort_values(['gross'],ascending=False).head(10)
movies_max1=movies_max[['actor_1_facebook_likes','actor_2_facebook_likes','actor_3_facebook_likes']]
movies_max1
创建 DataFrame,作为分组条形图的数据集
df = pd.DataFrame({'喜爱男1号':movies_max1['actor_1_facebook_likes'].values,
'喜爱男2号':movies_max1['actor_2_facebook_likes'].values,
'喜爱男3号':movies_max1['actor_3_facebook_likes'].values},
index=movies_max['movie_title'].str.strip())
df
这里我们对电影标题做了一个字符串去空格操作,是因为我们发现在创建分组条形图时横坐标总有异常方块,最后发现是因为 csv 中的原始数据电影标题前面有空格导致的。
绘制分组条形图
plt.figure()
df.plot.bar()
plt.title("票房前十电影喜爱男1号,男2号,男3号的人数的分组条形图")
plt.legend(ncol=3,loc=(0,1.1))
plt.xlabel('电影标题')
plt.ylabel('喜欢人数')
plt.show()
按年份统计每年电影总数量、彩色影片数量和黑白影片数量并绘制折线图(在同一个坐标系中绘制)。
# 每年电影总数量折线图
movies['title_year'].value_counts().sort_index().plot(kind='line',label='total number')
# 彩色影片数量折线图
movies[movies['color']=='Color']['title_year'].value_counts().sort_index().plot(kind='line',c='red',label='color number')
# 黑白影片数量折线图
movies[movies['color']!='Color']['title_year'].value_counts().sort_index().plot(kind='line',c='black',label='Black White number')
plt.legend(loc='upper left')
plt.xlabel('电影色彩')
plt.ylabel('电影数量')
plt.title('不同色彩电影数量折线图')
plt.legend(loc='upper left')
绘制不同类型的电影数量条形图和饼图。
提取 genres 列所有的电影类型,放入一个数组中;
# 创建字典用于存储电影类型
types = []
for tp in movies['genres']:
sp = tp.split('|')
for x in sp:
types.append(x)
# 格式化
types_df = pd.DataFrame({'genres':types})
可以看到,字典中共有14504个电影类型(包含重复值)。
统计字典中各种类型的数量
types_df_counts = types_df['genres'].value_counts()
types_df_counts
绘制不同类型的电影数量条形图
types_df_counts.plot(kind='bar')
plt.xlabel('电影类型')
plt.ylabel('电影数量')
plt.title('不同类型的电影数量条形图')
绘制不同类型的电影数量饼图
b1 = types_df_counts/types_df_counts.sum()
explode = (b1>=0.06)/20+0.02
types_df_counts.plot.pie(autopct='%1.1f%%',figsize=(8,8),\
label='',explode=explode)
plt.title('不同类型的电影数量饼图')
movie_score_20 = movies.sort_values(['imdb_score'],ascending=False).head(20)
movie_score_20[['movie_title','imdb_score']]
plt.scatter(x= movies.imdb_score,y=movies.movie_facebook_likes)
plt.xlabel('电影评分')
plt.ylabel('脸书喜欢人数')
plt.title('影片评分与受欢迎程度的关系散点图')
分享不易,点赞关注不迷路!