【数据分析实战】数据分析及可视化实战:豆瓣电影数据分析

本次数据:

来源豆瓣电影
40万条短评
50条以上评论电影1100多部

数据储存在sqlite数据库里
左侧点开Tables,可以看到有三张表
双击comment
在右侧点击数据标签可以查看
在这里插入图片描述
观察每行都有哪些数据

ID: 序号 TIME: 时间 MOVIEID: 豆瓣电影ID RATING: 该评论打分
CONTENT: 评论内容 CREATOR: 评论者 ADD_TIME:添加时间

“结巴”中文分词
https://github.com/fxsjy/jieba
• 支持三种分词模式: • 精确模式,试图将句子最精确地切开,适合文本分析; • 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常
快,但是不能解决歧义; • 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召
回率,适合用于搜索引擎分词。 • 支持繁体分词 • 支持自定义词典 • MIT 授权协议
安装:

pip install jieba
pip3 install jieba
import sqlite3
import pandas as pd
import jieba
from pyecharts.faker import Faker 
from pyecharts.charts import WordCloud
from pyecharts import options as opts
import math


#导入sqlite3和pandas,jiebad 词云图
#
FILTER_WORDS = ["知道",'电影',"片子","这么",'那么','怎么','是','的','这个','那个','什么','一部','这部','没有','觉得','认为',"\n",'....']
#建立过滤词列表   需要根据实际情况来调整过滤词列表 具体内容具体判断


def get_movie_id_list(min_comment_count):            #id
	movie_list = comment_data["MOVIEID"].value_counts()
	movie_list = movie_list[movie_list>min_comment_count]

	return movie_list.index

def get_comment_kw_counts(movie_id,count):     #汇总为一个函数,可以设置电影ID和要获取的评论数量
	comment_list = comment_data[comment_data["MOVIEID"]==movie_id]["CONTENT"]
	comment_str_all = ""
	for comment in comment_list:
		comment_str_all+=comment + "\n"
	seg_list =list(jieba.cut(comment_str_all))
	keywords_count = pd.Series(seg_list) 
	keywords_count = keywords_count[keywords_count.str.len()>1]
	keywords_count = keywords_count[~keywords_count.str.contains("|".join(FILTER_WORDS))]
	keywords_count = keywords_count.value_counts()[:count]

	return keywords_count

def get_movie_name_and_score(movie_id):
	movie_link = 'https://movie.douban.com/subject/{}/'.format(movie_id)
	#movie_data = pd.read_excel("douban_movie_data.xlsx")
	search_result = movie_data[movie_data["链接"]==movie_link].iloc[0]  #表格中包含重复的数 据,按照第一个筛选
	movie_name = search_result['电影名']
	movie_score = search_result['评分']

	return(movie_name,movie_score)



conn = sqlite3.connect("douban_comment_data.db")
comment_data = pd.read_sql_query("select*from comment;",conn)
movie_data = pd.read_excel("douban_movie_data.xlsx")
#连接数据库并读取表格 ‘select * from comment;‘是SQL语句表示从comment表格选取所有数据

#movie_list = comment_data["MOVIEID"].value_counts()
#movie_list = movie_list[movie_list>100]
#print(movie_list)
#print(movie_list.count())
#统计各个电影的评论数 筛选评论数大于100的电影

#print(get_movie_id_list(1000)
#
'''movie_id = "1292052"
comment_list = comment_data[comment_data["MOVIEID"]==movie_id]["CONTENT"]#根据ID筛选评论
#print(comment_list)

comment_str_all = ""
for comment in comment_list:
	comment_str_all+=comment + "\n"   #整合全部评论为一个字符串,以换行隔开

seg_list =list(jieba.cut(comment_str_all)) #获取分词后的列表
#print(seg_list)
keywords_count = pd.Series(seg_list)       #转换成Pandas的Series类型数据
#print(keywords_count)
keywords_count = keywords_count[keywords_count.str.len()>1] 
#利用str.len()筛选字符串长度 对于一个储存了字符串的Series数据
#可以使用.str.len()来获取各个字符串数据的长度


keywords_count = keywords_count[~keywords_count.str.contains("|".join(FILTER_WORDS))] 
#利用str. contains()筛选数据 .str.contains()里填一个字符串或者正则表达式
#反向选择不包含过滤词列表中词语的数据 表示取反 列表中True的变成False 列表中False的变成True
#print("|".join(FILTER_WORDS))    #re 知道|电影|片子|这么|那么|怎么|是|的|这个|那个|什么|一部|这部|没有|觉得|认为|

keywords_count = keywords_count.value_counts()[:30] #统计各个关键词的出现次数
print(keywords_count)'''

'''movie_id = "1292052"
keywords_counts = get_comment_keywords_counts(movie_id,30)

wordcloud = WordCloud()
wordcloud.add("",keywords_counts.index,keywords_counts.values,
	word_size_range=[20,100]
	
	)

wordcloud.render()'''

'''#根据电影ID在douban_movie_data找出电影名和评分
movie_link = 'https://movie.douban.com/subject/{}/'.fromat(movie_id)
movie_data = pd.read_excel("douban_movie_data.xlsx")
search_result = movie_data[movie_data["链接"]==movie_link].iloc[0]  #表格中包含重复的数 据,按照第一个筛选
movie_name = search_result['电影名']
movie_score = search_result['评分']'''

#movie_name,movie_id = get_movie_name_and_score("1292052")
#print(f'{movie_name} is {movie_id}')


#收集各个得分区域电影的TOP30关键ci
kw_list_by_score = [[]for i in range(10)]            #创建两个列表,储存关键词和出现次数  每个列表都含有十个列表
kw_counts_list_by_score = [[] for i in range(10)]

movie_id_list = get_movie_id_list(300)
for movie_id in movie_id_list:
	word_list = get_comment_kw_counts(movie_id,30)
	movie_name,movie_score = get_movie_name_and_score(movie_id)

	print(word_list) 

	try:
		kw_list_by_score[math.floor(movie_score)].extend(word_list.index)  #3.9 3.3 3
		kw_counts_list_by_score[math.floor(movie_score)].extend(word_list.values)
		

	except:
		print(movie_id)


'''print(kw_counts_list_by_score)
print(kw_list_by_score)'''

for i in range(10):                                 #每次创建一个DataFrame数据 保存该得分区间的TOP30关键词和出现总次数
	if kw_list_by_score[i]: 
		kw30_with_counts = pd.DataFrame({
				"kw":kw_list_by_score[i],
				"counts":kw_counts_list_by_score[i]

			})

		#print(kw30_with_counts)

		kw30_with_counts = kw30_with_counts.groupby("kw").sum()  #重复统计
		kw30_with_counts = kw30_with_counts.sort_values(by="counts",ascending=False)[:30]   #排序
		counts_sum = kw30_with_counts["counts"].sum()                               #统计关键词的总出现次数,并算出百分比 并储存为文件
		kw30_with_counts["percentage"] = kw30_with_counts["counts"]/counts_sum      #计算占比
		kw30_with_counts.to_csv("{}_movie_keywords.csv".format(i))
一、数据分析项目介绍 1. 项目所需的模块库介绍 pandas用法: 需要导入以下模块 import numpy as np import pandas as pd from pandas import Series, Dataframe 2.项目背景介绍 互联网电影资料库(Internet Movie Database,简称IMDB)是一个关于电影演员、电影、电视节目、电视明星和电影制作的在线数据库。电影作为艺术和娱乐载体已成为我们生活中的一部分,作为电影爱好者之一,希望通过分析了解电影市场大体情况,以便于以后选择电影观看。 使用的数据是IMDB美国票房排名前1000的电影数据,数据包含了电影名称,票房金额,上映年份,演职人员,IMDB评分,电影类型等信息,数据中的很多电影大家也比较熟悉。相信不少人都有这样的经历,当想要看一部电影的时候,会去百度一下谁是导演,谁是主演。如果导演是克里斯托弗•诺兰,心里已经给电影打了个8分以上的评分了。而阿汤哥的动作片,预期也都能肾上腺素飙升。对于已上映的电影,不少人会去豆瓣搜索现时的评分,或是前作的评价,若是豆瓣高分、高评论数,也会按奈不住去蹭下热度。如果要去电影院观看的话,想必不少人会更倾向选择动作片或者科幻大片这类特效丰富,影音冲击强烈的电影。近几年特效技术和3D动画的日渐成熟,影院观影已经是越来越多人的第一选择。 IMDB的资料中包括了影片的众多信息、演员、片长、内容介绍、分级、评论等。对于电影的评分目前使用最多的就是IMDB评分。 截至2018年6月21日,IMDB共收录了4,734,693部作品资料以及8,702,001名人物资料。 3.项目所需数据介绍 数据的属性包括:电影名称、评论数、评分、导演、上映时间、上映国家、主要演员、语言、IMDB评分等。 理解数据: color 、director_name 、num_critic_for_reviews、duration、director_facebook_likes 、actor_3_facebook_likes、actor_2_name 、actor_1_facebook_likes 、gross 、genres 、actor_1_name 、movie_title 、num_voted_users、cast_total_facebook_likes 、actor_3_name 、facenumber_in_poster 、plot_keywords 、movie_imdb_link 、num_user_for_reviews、language 、country、content_rating、budget、title_year 、actor_2_facebook_likes 、imdb_score 、aspect_ratio 、movie_facebook_likes 4.项目功能详细介绍 显示电影评分分布的情况; 电影数量与平均分年度变化的情况; 评论家评论数与评分的关系; 评分与电影票房的关系; 电影数量大于5前提下平均分前十的导演推荐的数据; 不同电影类型的年份累计分析; 电影时长的分布及时长是否和评分有相关性; 电影时长的分布及时长是否和评分有相关性。 二、数据分析过程 1.主要功能实现的类和方法介绍 # 清洗runtime电影时长列数据,可使用str.split()方法 df['runtime'] = df['runtime'].str.split('').str.get(0).astype(int) df['runtime'].head() # 清洗year列,使用str[:]选取年份数字并转换成int类型,使用df.unique()方法检查数据 df['year'] = df['year'].str[-5:-1].astype(int) df['year'].unique() 2. 数据分析过程代码和解释说明 导入包: 导入、查看、清洗数据: 评分分布图: 电影数量与平均分布年度变化: 评论家评论数&评分、评分&票房: 电影数量大于5平均分前十的导演: 统计不同年份、不同类型电影的数量: cumsum = df.groupby(['main_genre', 'year']).title.count() # 使用累加功能统计1980年起不同年份不同电影类型的累计数量,对于中间出现的缺失值,使用前值填充 genre_cumsum = cumsum.unstack(level=0).cumsum().ffill() # 只选取总数量大于50的电影类型数据 genre_cumsum = genre_cumsum.loc[:,genre_cumsum.iloc[-1,:] >= 50] # 根据电影类型统计数据作图 fig, ax2 = plt.subplots(figsize=(12,6)) genre_cumsum.plot(ax=ax12, legend=False, linewidth=3) # 添加数据标签 for i in last_row.iteritems(): if i[0] == 'Adventure' or i[0] == 'Biography' or i[0] == 'Horror': ax2.annotate('{} {}'.format(int(i[1]), i[0]), xy=(2018.5, i[1]-5), fontsize=12) else: ax2.annotate('{} {}'.format(int(i[1]), i[0]), xy=(2018.5, i[1]+5), fontsize=12) # 美化图表 ax2.set_title('The Aggregate Movies of Different Genres Over Years', fontsize=16) ax2.spines['top'].set_visible(False) ax2.spines['right'].set_visible(False) ax2.spines['left'].set_visible(False) ax2.tick_params(bottom=True, labelleft=False) ax2.set_xlabel('') plt.tight_layout() 电影时长的分布及时长是否和评分有相关性: fig, ax4 = plt.subplots() df['runtime_min'].hist(range=(70,210), bins=14, color=(114/255,158/255,206/255)) ax4.set_title('The Runtime Distribution of US Top Box Office Movies') ax4.spines['top'].set_visible(False) ax4.spines['left'].set_visible(False) ax4.spines['right'].set_visible(False) ax4.set_xticklabels(np.arange(70,220,10)) ax4.set_xticks(np.arange(70,220,10)) ax4.grid() 绘制时长和IMDB评分相关性: fig = plt.figure(figsize=(14,7)) sns.lmplot(data=df, x='runtime_min', y='imdb_rate') sns.despine() 三、数据分析结果评估 1、评分分布主要在5.0~8.0之间,3.0以下和9.0以上分布很少。如果8.0算为优秀,则优秀电影占比较少。 2、电影数量在1990~2000年间快速增长,2009年达到较高值。而电影的平均分整体上呈下降趋势。 3、评论家评论数与评分整体呈正相关关系,500以上评论家评论数对应的评分都高于6.0。 4、评分与票房整体呈正相关关系,但关系不强。 IMDB评分人数和电影票房的相关性很弱,高票房不代表评分人数多,低票房电影也能有大量的IMDB评分人数。 5、电影数量大于5平均分前十的导演:Christopher Nolan、Quentin Tarantino 、 Stanley Kubrick、 James Cameron 、Peter Jackson 、Alejandro G. Iñárritu 、David Fincher 、Martin Scorsese 、 Wes Anderson 、Paul Greengrass。 6. 前五大电影类型分别是动作片Action,喜剧片Comedy,动画片Animation,剧情片Drama,冒险片Adventure。1995年之前,动作片和喜剧片都是影院观众最喜爱的电影类型,对应的高票房数量不分伯仲,剧情片是另一相对流行的电影类型。1995年后,高票房的动作片快速增长,甩开了喜剧片。喜剧片随仍是高票房数量第二多的电影类型,但近几年增速明显放缓。高票房动画片进入榜单的时间最晚,但在1998年前后迎来明显增长,此后的十年里完成了对剧情片和冒险片的超越。如果动画片保持目前的增速,有望在之后的十几二十年里超越喜剧片,成为高票房数量第二的电影类型。 7. 时长和IMDB评分呈一定的相关性,时长短的电影既有高分也有低分,但时长超过160分钟的电影基本都能获得6分以上的分数,时长最长的两部电影甚至得到了接近9分的超高得分,IMDB评分接近或低于4分的电影时长均小于130分钟。丰富的剧情和长长的故事也许也是一种容易感染观众的方式,这也和之前提到的好的故事打动观众相呼应。 四、总结 数据分析的过程往往是一个从宏观到微观的过程。先从宏观上把握数据大体的情况,大胆地提出假设,然后再将数据进行细分,小心地求证。通过数据的对比,就很容易看出调整的效果。 有关活动效果的数据分析往往也会涉及数据的对比。具体的思路是从要分析的目的入手,首先思考造成这种情况的可能原因有什么,再从每个可能的原因中找到相应的数据,与要分析的目的的数据进行比较,看哪一个是造成该情况发生的主要原因。 这里要用到的是excel的图表工具,把每一种可能的数据都作出一个图表,与要分析的目的的数据图表进行比较,如果有某一个数据的变化曲线与之相差不多,则可以说这个所对应的原因是造成该情况发生的主要原因。 以上是分析活动的一些核心数据,核心数据的分析是最主要的,因为这直接反应了该活动最本质的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值