一、数据整理
1、合并+处理缺失值
# tmdb_5000_movies.csv budget :电影成本 genres:风格列表,按|分隔,最多5种风格 homepage:电影首页URL id :电影ID keywords:电影关键词,按|分隔,最多5种关键词 original_language:原始语言 original_title :电影名称 overview:剧情摘要 popularity:热度 production_companies:制作商 production_countries:制作地区 release_date:首次上映日期 revenue :收入 runtime :电影时长 spoken_languages:语言 status:是否发布 tagline:一句话说明一部电影(往往是海报上面的) title :电影名称 vote_average:平均分 vote_count:投票人数
# tmdb_5000_credits.csv movie_id:电影ID title:电影名称 cast:演员表 crew:制作团队(分析那些人经常出现在高票房的电影里面)
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline plt.style.use('ggplot') import json import warnings warnings.filterwarnings('ignore')#忽略警告 credits_file='D:/S072003Python/05DataMineML/tmdb_5000_credits.csv' movies_file='D:/S072003Python/05DataMineML/tmdb_5000_movies.csv' credits=pd.read_csv(credits_file) movies=pd.read_csv(movies_file)
# 合并文档 fulldf=pd.concat([credits,movies],axis=1)
# 选择子集 moviesnames=['movie_id','original_title','cast','crew','release_date','genres','keywords','production_companies','production_countries','revenue','budget','runtime','vote_average'] moviesdf=fulldf[moviesnames] moviesdf.head()
# 增加电影利润 moviesdf['profit']=moviesdf['revenue']-moviesdf['budget'] # 处理不理想数据 release_date_null=movies['release_date'].isnull() moviesdf.loc[release_date_null] moviesdf['release_date']=movies['release_date'].fillna('2014-06-01') moviesdf['release_date']=pd.to_datetime(moviesdf['release_date'],format='%Y-%m-%d') moviesdf.to_excel('moviesdf.xlsx',index=False) moviesdf.head() #3 找出runtime的缺失值 runtime_date_null=moviesdf['runtime'].isnull() moviesdf[runtime_date_null] values={'runtime:':98.0} values={'runtime:':81.0} moviesdf.fillna(value=values,limit=1,inplace=True) moviesdf.fillna(value=values,limit=2,inplace=True)
2、对于json格式的数据进行分割提取
# 如何从json的数据格式提取需要的数据 # 提取电影风格数据genres moviesdf['genreslist']=moviesdf['genres'].apply(json.loads) moviesdf.head(1) moviesdf['castlist']=moviesdf['cast'].apply(json.loads) moviesdf['countries']=moviesdf['production_countries'].apply(json.loads) # json.loads()将str类型的数据转换为dict类型 moviesdf['companies']=moviesdf['production_companies'].apply(json.loads) moviesdf['crewslist']=moviesdf['crew'].apply(json.loads) moviesdf.head(1)
定义函数处理genres:
# 每一个genres [{"id": 28, "name": "Action"}, {"id": 12, "name": "Adventure"}, {"id": 14, "name": "Fantasy"}, {"id": 878, "name": "Science Fiction"}]
#等于json格式的数据进行分割提取,通过自定义函数 def decode(column): z=[] for i in column: z.append(i['name']) return ' '.join(z) # 获取dict中第一个元素的name值 def decode1(column): z=[] for i in column: z.append(i['name']) return ''.join(z[0:1]) #切片,只输出第一个分隔
moviesdf['genresls']=moviesdf['genreslist'].apply(decode1)
二、 电影类型随时间变化怎么样?
# 电影类型与时间的关系 genres_list=set() # 获取所有的电影风格 for i in moviesdf['genresls'].str.split(' '): genres_list=set().union(i,genres_list) # 集合(set)是一个无序的不重复元素序列。可以使用大括号 { } 或者 set() 函数创建集合。 genres_list=list(genres_list) genres_list genres_list.remove('') # 去除空的元素 print(genres_list) moviesdf['releaseyear']=pd.to_datetime(moviesdf['release_date']).dt.year moviesdf.head(3) moviesdf.to_excel('moviesdfv3.xlsx',index=False)
得到的所有电影的风格genres_list
:
['Movie', 'Documentary', 'Comedy', 'Crime', 'Fantasy', 'History', 'Drama', 'Horror', 'Action', 'War', 'Foreign', 'Thriller', 'Fiction', 'Animation', 'Science', 'Music', 'Western', 'Romance', 'Family', 'TV', 'Mystery', 'Adventure']
目的:由于每部电影不只一种风格,则为每种风格添加一个字段,如果该电影包含这种风格则填1,否则填0。
for genre in genres_list: moviesdf[genre]=moviesdf['genresls'].str.contains(genre).apply(lambda x:1 if x else 0) moviesdf[genre].tail() moviesdf.head(2)
genre_year=moviesdf.loc[:,genres_list] genre_year.index=moviesdf['releaseyear'] genresdf=genre_year.groupby('releaseyear').sum() genresdf genresdf.plot(figsize=(16,10))
genresdfsum=genresdf.sum(axis=0).sort_values(ascending=False) genresdfsum
genresdfsum
:拿到从1916到2017年所有风格电影数据的总和
Drama 2297 Comedy 1722 Thriller 1274 Action 1154 Romance 894 Adventure 790 Crime 696 Fiction 535 Science 535 Horror 519 Family 513 Fantasy 424 Mystery 348 Animation 234 History 197 Music 185 War 144 Documentary 110 Western 82 Foreign 34 TV 8 Movie 8 dtype: int64
genresdfsum.sort_values().plot(kind='barh',label='genres') # 如果是kind='bar'则横纵坐标交换 plt.rcParams['font.sans-serif']=['Microsoft YaHei'] # 使用微软雅黑的字体 plt.title('电影类型数量排名统计图') plt.xlabel('电影数量') plt.ylabel('电影类型') plt.show()
# 计算电影类型的饼图 genres_pie=genresdfsum/genresdfsum.sum() others=0.01 genres_pie_otr=genres_pie[genres_pie>=others] genres_pie_otr['other']=genres_pie[genres_pie<others].sum() explode=(genres_pie_otr<=0.02)/10+0.04 genres_pie_otr.plot(kind='pie',label='',startangle=50,shadow=False,figsize=(10,10),autopct='%1.1f%%',explode=explode)
# 电影类型和时间关系的分析 plt.figure(figsize=(16,10)) plt.plot(genresdf,label=genresdf.columns) plt.xticks(range(1905,2021,5)) plt.legend(genresdf) plt.title('电影类型与时间',fontsize=15) plt.xlabel('年份',fontsize=15) plt.ylabel('%ddir影数量',fontsize=15) plt.show()
三、 电影类型与利润的关系
# 电影类型与利润的关系 mean_genre_profit=pd.DataFrame(index=genres_list) mean_genre_profit.head() newarray=[] for genre in genres_list: # moviesdf.groupby('War',as_index=True)['profit'].mean() # 使得War得到两组数据,第一组为0,即不是War类型的平均值,无意义,因此下面只取第二组1 newarray.append(moviesdf.groupby(genre,as_index=True)['profit'].mean()) newarray2=[] for i in range(len(genres_list)): newarray2.append(newarray[i][1]) # 这里取的是第二个数据, mean_genre_profit['mean_profit']=newarray2 mean_genre_profit.head(17)
得到的mean_profit
:
mean_profit Movie -1.150000e+06 Documentary 7.185600e+06 Comedy 4.597608e+07 Crime 3.830085e+07 Fantasy 1.297936e+08 History 2.762010e+07 Drama 3.143791e+07 Horror 2.897105e+07 Action 8.970235e+07 War 4.887342e+07 Foreign -2.934369e+05 Thriller 4.907608e+07 Fiction 1.005910e+08 Animation 1.592271e+08 Science 1.005910e+08 Music 3.254800e+07 Western 1.916726e+07 Romance 3.969103e+07 Family 1.116260e+08 TV -1.150000e+06 Mystery 4.755644e+07 Adventure 1.423333e+08
# 绘制电影类型与平均利润的关系 mean_genre_profit.sort_values(by='mean_profit').plot(kind='barh') plt.xlabel('平均利润') plt.ylabel('电影类型') plt.title('电影类型与平均利润的关系')