利用棒棒糖图探索Office (US)的IMDB评分

import numpy as np
import pandas as pd
import matplotlib.colors as mc
import matplotlib.image as image
import matplotlib.pyplot as pltfrom matplotlib.cm import ScalarMappable
from matplotlib.lines import Line2D
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from palettable import cartocolors # 获得好看的颜色

数据探索

以下数据如果有需要的同学可关注公众号HsuHeinrich,回复【数据可视化】自动获取~

df_office = pd.read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-03-17/office_ratings.csv")
df_office.head()

image-20240129175359876

season:季度

episode:剧集编号

imdb_rating:IMDB评级

total_votes:每个评级使用的投票数

df_office_avg = df_office.sort_values(["season", "episode"])
# 生成episode_id:自增序列
df_office_avg["episode_id"] = np.arange(len(df_office_avg)) + 1
df_office_avg["episode_mod"] =  df_office_avg["episode_id"] + (9 * df_office_avg["season"])
df_office_avg = df_office_avg.assign(avg = df_office_avg.groupby("season")["imdb_rating"].transform("mean"),mid = df_office_avg.groupby("season")["episode_mod"].transform("mean")
)df_office_avg.head()

image-20240129175424360

创建df_lines数据集:以便于绘制表示每个季度评分平均值的水平线,这些线将在每个季度的第一个和最后一个剧集之间延伸,并稍微超过这些点

df_lines = df_office_avg.groupby("season").agg(start_x = ("episode_mod", min),end_x = ("episode_mod", max),y = ("avg", max) # 每个season的avg一样,用max获取唯一值
).reset_index()# 在每个方向上稍微延长水平线
df_lines["start_x"] -= 5
df_lines["end_x"] += 5df_lines = pd.melt(df_lines, id_vars=["season", "y"], value_vars=["start_x", "end_x"], var_name="type", value_name="x"
)
df_lines["x_group"] = np.where(df_lines["type"] == "start_x", df_lines["x"] + 0.1, df_lines["x"] - 0.1)
df_lines["x_group"] = np.where((df_lines["type"] == "start_x").values & (df_lines["x"] == np.min(df_lines["x"])).values, df_lines["x_group"] - 0.1, df_lines["x_group"]
)
df_lines["x_group"] = np.where((df_lines["type"] == "end_x").values & (df_lines["x"] == np.max(df_lines["x"])).values, df_lines["x_group"] + 0.1, df_lines["x_group"]
)
df_lines = df_lines.sort_values(["season", "x_group"])
df_lines.head()

image-20240129175446112

绘制棒棒糖图

图片logo为the-office,可在网上自行下载,也可以关注公众号HsuHeinrich,回复【可视化素材】自动获取~

def adjust_lightness(color, amount=0.5):'''调整颜色亮度:低于 1 的值使其变暗,高于 1 的值使其变亮'''import matplotlib.colors as mcimport colorsystry:c = mc.cnames[color]except:c = colorc = colorsys.rgb_to_hls(*mc.to_rgb(c))return colorsys.hls_to_rgb(c[0], max(0, min(1, amount * c[1])), c[2])
# 定义一些变量# 颜色
GREY82 = "#d1d1d1"
GREY70 = "#B3B3B3"
GREY40 = "#666666"
GREY30 = "#4d4d4d"
BG_WHITE = "#fafaf5"# 季节颜色调整
COLORS = ["#486090", "#D7BFA6", "#6078A8", "#9CCCCC", "#7890A8","#C7B0C1", "#B5C9C9", "#90A8C0", "#A8A890"]
COLORS_DARK = [adjust_lightness(color, 0.8) for color in COLORS]
COLORS_LIGHT = [adjust_lightness(color, 1.2) for color in COLORS]# 三种颜色调整函数
cmap_regular = mc.LinearSegmentedColormap.from_list("regular", COLORS)
cmap_dark = mc.LinearSegmentedColormap.from_list("dark", COLORS_DARK)
cmap_light = mc.LinearSegmentedColormap.from_list("light", COLORS_LIGHT)# 对季节进行缩放
normalize = mc.Normalize(vmin=1, vmax=9)# 图片存储
IMAGE = image.imread("pic/the-office.jpg")# 水平线
HLINES = [6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10]
VOTES_MAX = df_office_avg["total_votes"].max()
VOTES_MIN = df_office_avg["total_votes"].min()# 缩放票数,用于棒棒糖的大小
def scale_to_interval(x, low=15, high=150):return ((x - VOTES_MIN) / (VOTES_MAX - VOTES_MIN)) * (high - low) + low
# 初始化布局
fig, ax = plt.subplots(figsize = (15, 10))# 背景颜色
fig.patch.set_facecolor(BG_WHITE)
ax.set_facecolor(BG_WHITE)# 绘制水平参考线,zorder=0位于图层最下方
for h in HLINES:plt.axhline(h, color=GREY82, zorder=0)# 垂直线段:代表剧集评分与平均评分的偏差
plt.vlines(x="episode_mod", ymin="imdb_rating", ymax="avg",color=cmap_light(normalize(df_office_avg["season"])),data = df_office_avg
)# 水平线:连接平均值的灰线
plt.plot("x", "y", "-", color=GREY40, data=df_lines)# 水平线:每个赛季的平均分 
for season in df_lines["season"].unique():d = df_lines[df_lines["season"] == season]plt.plot("x_group", "y", "", color=cmap_dark(normalize(season)), lw=5, data=d, solid_capstyle="butt")# 点:每集的评分,大小由投票数决定
plt.scatter("episode_mod", "imdb_rating",s = scale_to_interval(df_office_avg["total_votes"]),color=cmap_regular(normalize(df_office_avg["season"])), data=df_office_avg,zorder=3
)# Season标签
midpoints = df_office_avg["mid"].unique()
for season, mid in enumerate(midpoints):color = cmap_dark(normalize(season + 1))plt.text(mid, 10.12, f" Season {season + 1} ", color=color,weight="bold",ha="center",va="center",fontname="Special Elite",fontsize=11,bbox=dict(facecolor="none", edgecolor=color, linewidth=1,boxstyle="round", pad=0.2))# ------------------------自定义布局------------------------# 隐藏边框
ax.spines["right"].set_color("none")
ax.spines["top"].set_color("none")
ax.spines["bottom"].set_color("none")
ax.spines["left"].set_color("none")# 自定义y轴
plt.tick_params(axis="y", labelright=True, length=0)
plt.yticks(HLINES, fontname="Roboto", fontsize=11, color=GREY30)
plt.ylim(0.98 * 6.5, 10.2 * 1.02)# 移除x刻度
plt.xticks([], "")# 设置y标签
plt.ylabel("IMDb Rating", fontname="Roboto", fontsize=14)# 添加著作信息
plt.text(0.5, -0.03, "Visualization by Cédric Scherer  •  Data by IMDb via data.world  •  Fanart Logo by ArieS", fontname="Special Elite", fontsize=11, color=GREY70,ha="center", va="center", transform=ax.transAxes # so coordinates are in terms of the axis.
)# 放置图片logo
ab = AnnotationBbox(OffsetImage(IMAGE, zoom=0.2), (1, 6.75), xycoords="data", box_alignment=(0, 0.5),pad=0, frameon=False
)
ax.add_artist(ab)# ------------------------自定义图例------------------------# 水平图例点及其标签的位置
x_pos = [0.44, 0.48, 0.52, 0.56]
votes = [2000, 4000, 6000, 8000]# 绘制图例点
plt.scatter(x_pos, [0.065] * 4, s=scale_to_interval(np.array(votes)), color="black",transform=ax.transAxes
)# 添加图例标签名
plt.text(0.5, 0.0875, "Votes per Episode", fontname="Roboto", fontsize=10, ha="center", transform=ax.transAxes)# 将图例放在图例标记下方
for (xpos, vote) in zip(x_pos, votes):plt.text(xpos, 0.035,  f"{vote}", fontname="Roboto", fontsize=9, ha="center", transform=ax.transAxes)plt.show()

png

参考:The Office Ratings with Python and Matplotlib

共勉~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/921009.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/921009.shtml
英文地址,请注明出处:http://en.pswp.cn/news/921009.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zephyr如何注册设备实例

设备树 → 编译期生成 → 运行时访问 流程图&#xff1a;Zephyr dev->config 工作流程设备树 (.dts) ───────────────────────────── anx745139 {compatible "analogix,anx7451";reg <0x39>;reset-gpios <&gpio1 5 …

Spring Boot 日志框架选择指南:Logback vs Log4j2

在 Spring Boot 应用中&#xff0c;您需要明确选择一个日志框架 - ​​不能同时使用两种日志实现​​。以下是关于 spring-boot-starter-log4j2和 spring-boot-starter-logging的全面比较和选择建议&#xff1a;核心区别特性spring-boot-starter-log4j2(Log4j2)spring-boot-sta…

Axure科技感可视化原型案例:赋能设计与研发的宝藏资源

在当今数字化浪潮中&#xff0c;数据可视化已成为企业洞察市场、优化运营、快速决策不可或缺的工具。Axure&#xff0c;作为原型设计领域的领航者&#xff0c;凭借其强大的功能和丰富的资源&#xff0c;为数据可视化大屏的设计注入了科技活力与创新元素。本文将深入探讨Axure科…

跨境电商账号风控核心:IP纯净度与浏览器指纹的防护策略

对跨境电商从业者而言&#xff0c;账号突然被封是常见却令人头痛的问题。即便严格遵守平台规则、使用代理IP&#xff0c;账号仍可能因风控策略而受限。这背后&#xff0c;IP纯净度与浏览器指纹识别是两大常被忽视却至关重要的技术因素。本文将从技术角度解析其原理&#xff0c;…

daily notes[7]

文章目录perl notereferencesperl note A hash in perl can be initialized with array,for example: my %numbers ("one", 1, "two", 2); print $fruit_color{"one"}; it is wonderful that the hash can be sliced to result in an array …

WPF迁移avalonia之图像处理(一)

从WPF迁移到avalonia中&#xff0c;对于图像处理部分&#xff0c;在WPF常用System.Windows.Drawing中图像处理元素&#xff0c;但是在开发avalonia应用时考虑跨平台特性&#xff0c;则必须有对应的跨平台替换方案。主要考虑Avalonia.Media.Imaging.Bitmap和SkiaSharp.SKBitmap …

242. 有效的字母异位词| 349. 两个数组的交集

242. 有效的字母异位词 nums [0]*26 : 这行代码创建了一个包含26个0的列表&#xff0c;这个列表通常用于计数或者作为某种映射的基础&#xff0c;比如统计字符串中每个字母出现的次数&#xff08;假设只考虑小写字母a-z&#xff09;。 ord() Python 中的一个内置函数&#x…

HTML第二课:块级元素

HTML第二课&#xff1a;块级元素块级元素块级元素 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang"zh-CN"> <head><meta http-equiv"Content-…

微论-突触的作用赋能思考(可能是下一代人工智能架构的启发式理论)

突触智能&#xff1a;微观结构与宏观智慧的桥梁摘要&#xff1a;传统人工智能模型&#xff0c;尤其是深度学习&#xff0c;将突触简单抽象为一个静态的权重参数&#xff0c;这极大地简化了生物计算的复杂性。本文受启发于生物突触的微观功能&#xff0c;提出了一种新的智能架构…

ARM - GPIO 标准库开发

一、STM32MP157AAA开发板套件介绍1.1 核心板 - 主板如图所示&#xff1a;主板各部分介绍1.2 IO 拓展板如图所示&#xff1a;IO拓展板各部分介绍开发板名称&#xff08;硬件平台&#xff09;&#xff1a;FS-MP1A主控制器&#xff1a;STM32MP157AAA3 Cortex-A7 * 2 Cortex-M4 -…

橙武低代码:不仅仅是云SaaS,更是云端开发+本地部署的新范式

版权归作者所有&#xff0c;转载请注明出处。 一、低代码的时代背景 在过去十年里&#xff0c;软件研发模式经历了巨大的演变。从传统的瀑布开发&#xff0c;到敏捷、DevOps&#xff0c;再到如今的低代码/无代码平台&#xff0c;研发效率和交付模式发生了根本性变化。低代码的…

神经语言学视角:脑科学与NLP深层分析技术的交叉融合

引言&#xff1a;从“统计拟合”到“类人理解”——NLP的下一个范式近年来&#xff0c;以Transformer架构为核心的大型语言模型&#xff08;LLM&#xff09;在自然语言处理&#xff08;NLP&#xff09;领域取得了前所未有的成功 。它们能够生成流畅的文本、回答复杂的问题&…

Coze源码分析-工作空间-项目查询-前端源码

前言 本文将深入分析Coze Studio项目中用户登录后进入工作空间查看和管理项目的前端实现&#xff0c;通过源码解读来理解工作空间项目开发功能的架构设计和技术实现。Coze Studio采用了现代化的React TypeScript技术栈&#xff0c;结合微前端架构和模块化设计&#xff0c;为用…

【系统架构师设计(9)】系统设计:结构化设计与面向对象设计

文章目录一、核心思想&#xff1a;模块化与对象化的设计哲学1、结构化设计的核心思想2、面向对象设计的核心思想3、两种设计方法的本质区别二、结构化设计知识点1、设计阶段2、设计原则3、 内聚类型&#xff08;从低到高&#xff09;耦合类型&#xff08;从低到高&#xff09;模…

还在从零开发AI应用?这个项目直接给你500个现成方案!!!

大家好&#xff0c;我是顾北&#xff0c;一名AI应用探索者&#xff0c;也是GitHub开源项目收集者。昨晚又在GitHub上瞎逛...咦&#xff0c;碰到了一个特别有意思的项目。说实话吧&#xff0c;作为一个天天折腾AI工具的人&#xff0c;见过的项目没有一千也有八百了&#xff0c;但…

react+taro的使用整理

前言&#xff1a; 本文主要整理下我们跨段工具taro的具体使用方法与相关资料。 taro官网&#xff1a; 安装及使用 | Taro 文档 安装&#xff1a; 全局脚手架安装&#xff1a; npm install -g tarojs/cli 使用脚手架安装我们的taro项目 taro init myApp 运行到不同小程序教…

从 “容器保姆” 到 “云原生王者”:K8s 全方位指南

目录 开头专业总结 一、先搞懂&#xff1a;K8s 到底是什么&#xff1f;能解决什么痛点&#xff1f; 1. K8s 的本质 2. 核心用处&#xff08;解决的痛点&#xff09; 二、K8s 核心知识点&#xff1a;组件与概念&#xff08;标重点&#xff01;&#xff09; &#xff08;一…

03.《交换的底层逻辑:从基础到应用》

交换基础 文章目录交换基础MAC 地址&#xff1a;设备的 “全球唯一身份证”MAC 地址的基本属性MAC 地址的三类类型&#xff08;按通信范围划分&#xff09;以太帧以太帧的两个标准格式1. Ethernet_II 格式&#xff08;常用&#xff09;2. IEEE 802.3 格式&#xff08;少用&…

火语言 RPA 界面应用生成:轻量化开发核心优势

火语言 RPA 界面应用生成功能&#xff0c;主打 “低门槛、快落地”&#xff0c;无需复杂开发环境与专业技术&#xff0c;就能快速实现需求验证与工具搭建&#xff0c;尤其适配中小团队与个人&#xff0c;核心优势如下&#xff1a;​一、1 小时搞定需求验证&#xff1a;3 步落地…

第三方软件测试机构【多语言开发(PHP/Java/Python)WEB 应用的安全专业测试流程】

PHP应用测试安全 文件包含漏洞&#xff1a;检测include/require函数参数未过滤场景&#xff08;如?page../../../etc/passwd&#xff09; 命令注入&#xff1a;检查system()/exec()函数输入验证&#xff08;如| cat /etc/passwd&#xff09; 会话安全&#xff1a;验证session …