python计算各类型电影的评分,Moviedata-10M电影数据集统计分析之源码分享(Python)...

之前写过一篇电影数据分析的文章”豆瓣13万电影数据统计与分析“,引起了一些读者的关注,并且在后台咨询我是否可以分享下源码。为了满足大家的需要,我在五一期间将源码略作整理了下,并从中筛选了几个绘图源码在这里分享给大家,如有疑问,可在评论区留言。特别说明下,文中分析的数据来自电影数据集Moviedata-10M中的movies.csv文件,需要的童鞋可以按照官方的说明进行下载即可。

准备工作

在进行源码分享之前,这里先说说我们的运行环境吧,我是使用jupyter进行实验的(强烈推荐),python 3.6版本,依赖的相关库如下:

pandas

matplotlib

seaborn

numpy

WordCloud

imageio

squarify

如果对上面的库不了解或者不会安装的,请自行查阅,这里就不一一细说了。

数据加载

由于文件是csv文件,所以加载数据只需要使用python里面的pandas库即可,采用pandas中的read_csv就可以将csv中的数据加载到内存中,代码如下:

1

2

3

4import csv

import pandas as pd

import random

movies = pd.read_csv("../data/movies.csv", encoding="utf-8")

统计分析

在豆瓣13万电影数据统计与分析一文,我从不同的维度对电影数据进行了分析,在这里不会将全部的源码分享出来,但是会将核心内容贴出来。

按上映年份统计电影

首先导入相关依赖库,主要是matplotlib,如下:

1

2

3import matplotlib.pyplot as plt

import matplotlib

matplotlib.matplotlib_fname()

下面这几行代码是为了解决图表中的中文乱码问题,仅供参考:

1

2

3

4

5

6

7#解决matplotlib 乱码

matplotlib.rcParams['font.sans-serif'] = ['SimHei']

matplotlib.rcParams['font.family']='sans-serif'

#解决负号'-'显示为方块的问题

matplotlib.rcParams['axes.unicode_minus'] = False

from matplotlib.font_manager import _rebuild

_rebuild()

在绘制图表之前,我们需要对数据进行处理,构造我们需要的数据格式:

1

2

3

4

5

6

7

8

9

10#如果year字段为空,就从release_date进行截取

def map_year(x):

year = x["year"]

if year == 0:

year = str(x["release_date"]).split("-")[0]

return str(year)

movies["year2"] = movies.apply(lambda x: map_year(x), axis=1)

#获取2020年之前上映的电影

movies = movies[movies["year2"]

得到2020年之前的电影之后,我们再分组统计每年上映的电影数量

1

2

3year_grp = movies.groupby("year2").size().reset_index(name="num") \

.sort_values(by="year2", ascending=True)

year_grp = year_grp.rename(columns={"year2":"year"})

接着,按照年份和上映的电影量进行绘图,首先分享下散点图的绘制方法,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18import seaborn as sns

#散点图

def draw_stripplot(df, df_x, df_y, title="Title", ylabel="Y", savepath="defalt.png"):

# draw stripplot start

fig, ax = plt.subplots(figsize=(20,10), dpi= 80)

sns.stripplot(df_x, df_y, jitter=0.25, size=8, ax=ax, linewidth=.5)

# decoration

plt.gca().set_xticklabels(df_x, rotation=90, horizontalalignment= 'right')

plt.title(title, fontsize=16)

plt.ylabel(ylabel)

plt.savefig(savepath)

plt.show()

draw_stripplot(year_grp, year_grp.year, year_grp.num,

title="Number Of Movies Released Each Year(1873-2019)",

ylabel='# Number',

savepath="result/movies_number_of_each_year_stripplot.png")

draw_stripplot方法是可以共用的,如果其他的聚合数据生成了,也可以调用上面的方法。得到的图表如下所示:

dfc15f97fb8a9e72944ca018de01da1c.png

Fig 1.每年上映的电影数(趋势图)

按评分统计电影

首先分组统计出每个评分的电影数量

1

2

3df = movies.groupby('douban_score').size().reset_index(name='counts')

df = df[df["douban_score"]>0]

df["douban_score"] = df.douban_score.astype("str")

采用movies[movies["douban_score"] > 0]["douban_score"].mean()可以统计出电影的平均得分为6.63。

接着编写柱状图绘制函数,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22#柱状图

def draw_barplot(df, df_x, df_y, title="Title", ylabel="# Y",

savepath="default.png", fontsize=5, x_fontsize=10):

all_colors = list(plt.cm.colors.cnames.keys())

random.seed(100)

c = random.choices(all_colors, k=df_x.shape[0])

# Plot Bars柱状

plt.figure(figsize=(20,10), dpi= 200)

plt.bar(df_x, df_y, color=c, width=.5)

for i, val in enumerate(df_y.values):

plt.text(i, val, int(val), horizontalalignment='center',

verticalalignment='bottom',

fontdict={'fontweight':200, 'size':fontsize})

# Decoration

plt.gca().set_xticklabels(df_x, rotation=90, horizontalalignment= 'right',

fontdict={"size":x_fontsize})

plt.title(title, fontsize=16)

plt.ylabel(ylabel)

plt.savefig(savepath)

plt.show()

将数据采用上面别写函数进行渲染:

1

2

3draw_barplot(df, df.douban_score, df.counts,

title="Movie Statistics For Each Score",

ylabel='# Score', savepath="result/movie_stat_by_score.png", fontsize=10)

得到的柱状图如下所示:

9a6af7ab175d77660dd5144fb4133a0b.png

Fig 2.各个评分下的电影数统计

按照国家进行统计

首先根据国家进行聚合,

1

2

3

4

5movies_regions = movies

movies_regions["regions"] = movies_regions.regions \

.apply(lambda x: x.split("/")[0].split(" ")[0].strip())

df = movies_regions.groupby('regions').size().reset_index(name='counts')

df = df[df["regions"]!=""].sort_values(by=["counts"], ascending=False)[:50]

然后调用draw_barplot函数即可:

1

2

3draw_barplot(df, df.regions, df.counts,

title="Movie Statistics For Each Region", ylabel='# Number',

savepath="result/movies_stat_by_regions.png", fontsize=8,x_fontsize=12)

结果图如下:

72f01374d89a50fe56e82471ba0dfb50.png

Fig 3.按发行地域统计电影数(Top 50的发行地域)

按语言进行统计

数据构建

1

2

3

4

5

6

7df = movies.groupby('languages').size().reset_index(name='counts')

df = df[df["languages"]!=""]

df = movies.languages.apply(lambda x: x.split("/")[-1].split(" ")[0]) \

.reset_index(name="languages").drop(columns="id")

df = df.groupby("languages").size().reset_index(name='counts')

df = df[df["languages"]!=""]

df = df.sort_values(by=["counts"], ascending=False)[:20]

绘制饼状图,并进行渲染:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38import matplotlib.pyplot as plt

import numpy as np

def draw_pieplot(df, df_x, df_y,

title="Title",

subtitle="subtitle",

savepath="default.png"):

# Draw Plot

fig, ax = plt.subplots(figsize=(12, 7), subplot_kw=dict(aspect="equal"), dpi= 80)

data = df_y

categories = df_x

explode = np.zeros(df_x.shape[0])

explode[3] = 0.1

def func(pct, allvals):

absolute = int(pct/100.*np.sum(allvals))

return "{:.1f}% ({:d} )".format(pct, absolute)

wedges, texts, autotexts = ax.pie(data,

autopct=lambda pct: func(pct, data),

textprops=dict(color="w"),

colors=plt.cm.Dark2.colors,

startangle=140)

# Decoration

ax.legend(wedges, categories,

title=subtitle, loc="center left",

bbox_to_anchor=(1, 0, 0.5, 1))

plt.setp(autotexts, size=10, weight=700)

ax.set_title(title)

plt.savefig(savepath)

plt.show()

draw_pieplot(df, df.languages, df.counts,

title="Statistics By Languages: Pie Chart",

subtitle="Languages",

savepath="result/movie_language_stat_pieplot.png")

结果图如下:

5ed3b694c2cc506f2152d04545839b61.png

Fig 4.按语言统计电影数

对中国的电影进行分析

同理,首先构造数据格式:

1

2

3

4

5

6

7

8

9movies_china = movies[movies.regions.str.startswith("中国") | \

movies.regions.str.startswith("香港") | \

movies.regions.str.startswith("台湾") | \

movies.regions.str.startswith("澳门")]

df = movies_china.reset_index().groupby('year').size().reset_index(name="counts")

df = df[df["year"]!=""][df["year"]!=0]

df = df.sort_values(by="year", ascending=True)

#df["counts"] = df.counts.astype("str")

接着绘制线性趋势图:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26def draw_plot_liner2(df, df_x, df_y,

x_name,

y_name,

title="Title",

ylabel="Y",

savepath="defalt.png"):

# Draw Plot - liner

plt.figure(figsize=(16,10), dpi= 80)

plt.plot(x_name, y_name, data=df, color='tab:red')

plt.yticks(fontsize=12, alpha=.7)

plt.title(title, fontsize=22)

plt.ylabel(ylabel)

plt.grid(axis='both', alpha=.3)

# Remove borders

plt.gca().spines["top"].set_alpha(0.0)

plt.gca().spines["bottom"].set_alpha(0.3)

plt.gca().spines["right"].set_alpha(0.0)

#plt.gca().spines["left"].set_alpha(0.3)

plt.savefig(savepath)

plt.show()

draw_plot_liner2(df, df.year, df.counts,'year','counts',

title="Statistics of Movie_China For Each Year",

ylabel='# Number', savepath="result//movies_china_each_year.png")

最后得到的趋势图如下:

7c30dc21bbd8f2c6fbcb4346c8ec6675.png

Fig 5.中国每年的电影数量统计

如果需要渲染多个国家进行对比,只需要将多个国家的数据进行聚合然后一个个绘制到图上即可。

词云

电影类型词云

如果想要绘制类型词云,需要上面提到的WordCloud库。

1

2

3from wordcloud import WordCloud

import collections

import imageio

当具备这些之后,我们首先要准备数据,取出电影标签,然后进行词频统计,

1

2

3

4

5object_list = movies.genres.tolist()

word_list = []

for words in object_list:

word_list.extend(words.split("/"))

word_counts = collections.Counter(word_list) # 对分词做词频统计

接着调用WordCloud库进行分析

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16b_mask = imageio.imread("./data/bg_my.jpeg") #如果运行到这里找不到图片,请自行替换图片即可

wc = WordCloud(font_path="Hiragino Sans GB.ttc", # 字体

background_color = 'white', # 背景色

max_words = 2000, # 最大显示单词数

#width=1000,

#height=500,

max_font_size = 160, # 频率最大单词字体大小

mask=b_mask

#stopwords = stopwords # 过滤噪声词

).generate_from_frequencies(word_counts)

wc.to_file("genres_cloud.png")

plt.imshow(wc, interpolation="bilinear")

plt.axis("off")

plt.show()

如果词库比较大的话,时间需要久一点,最后得到的图片如下:

c7827c423a0a97494c5b2a322b44d4ad.png

Fig 6.电影类型词云

标签词云也是类似的,只需hexo要重新渲染下数据即可。

结束语

文章共介绍了散点图、线性图、柱状图、饼状图、词云这几个核心图表的绘制,只要下载了相关库,那么构造出相应的数据格式之后,代码可以直接运行,后续我会考虑以jupyter文件分享出来,大家可以关注下我的公众号:【斗码小院】,相关内容会第一时间发布到公众号中,如果相关问题,也可以在公众号的“关于小院”一栏进行留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值