用Matplotlib绘制柱状图(仿照极客湾的Mate60 Pro评测跑分图)

2023-10-11 23:50

本文主要是介绍用Matplotlib绘制柱状图(仿照极客湾的Mate60 Pro评测跑分图),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

用Matplotlib绘制柱状图(仿照极客湾的Mate60 Pro评测跑分图)

  • 1、基础绘制
  • 2、进阶版本
    • 2.1 颜色的设置
      • 2.1.1、背景颜色的设置
      • 2.1.2、字体颜色的设置
    • 2.2 bar数值显示
  • 3、高级版本
    • 3.1 带圆角的bar
    • 3.2 标题和Logo
      • 3.2.1 标题
      • 3.2.2 Logo
  • 最终完整代码

极客湾的Mate60 Pro评测跑分图

大家好!前段时间刷新闻看到一张Mate60 Pro的一张测评图,感觉挺有这种风格的数据展示方式挺有科技感。然后有个想法,想用Matplotlib去复现一下。这两天闲了下来,写个blog,打算从入门、进阶到高级三个阶段绘制这个柱状图。

注意,如果你用的是版本比较低的matplotlib和python,直接拿我的代码使用的话,有些是可能会报错的哦!

#我的matplotlib的版本
import matplotlib
print(matplotlib.__version__)
3.6.3

1、基础绘制

仔细观察这个图,图中内容比较简单,主要是两组数据即多核与单核的跑分。这两组数据比较好的表现方式就是柱状图(当然,横向和纵向的表达方式都是可以的),例图中呈现的是横向柱状图。

所以,咱们从最简单barh函数开始吧。

废话不多说,直接上代码

import numpy as np
import matplotlib.pyplot as pltplt.rcParams['font.family'] = 'Microsoft Yahei'
plt.rcParams['axes.unicode_minus'] = FalseMulticore = np.array([4019,3770,5150,3830,3765,3395,3820])
Singlecore = np.array([1005,1019,1508,1255,1127,903,907])
name = ['麒麟9000S\n华为Mate 60Pro','麒麟9000\n华为Mate 40Pro','骁龙8 Gen2\n小米13','骁龙8 Gen1\nMoto edge X30','骁龙888\n魅族18','骁龙865\n一加8 Pro','天玑8100\n红米K50']
#多核的数据
Multicore = np.array([4019,3770,5150,3830,3765,3395,3820])
#单核的数据
Singlecore = np.array([1005,1019,1508,1255,1127,903,907])
x = np.arange(len(Multicore))fig,ax = plt.subplots(figsize=(12,5))
height = 0.25
ax.barh(x-0.7*height,Multicore ,height=height,label='多核')
ax.barh(x+0.7*height,Singlecore,height=height,label='单核')
ax.set_yticks(x,labels=name,rotation=0)
ax.legend()
ax.invert_yaxis()
plt.show()

显示结果

基础版本

基础版本比较好理解,就是两个barh就可以画出来,唯一需要注意的就是柱子的位置和height大小。

2、进阶版本

有了基础版本,就有了复现例图的基础框架了。
进阶版本就是在此基础上,美化图片中的元素,在细节上尽可能做到一致。

2.1 颜色的设置

2.1.1、背景颜色的设置

图中的背景色是黑色,因此

fig,ax = plt.subplots(figsize=(12,5),facecolor='k') #图片的背景设置为黑色
ax.set_facecolor('k') #axes的背景颜色设置为黑色

与背景无关的元素就不能有黑色的存在,否则就混在一起,看不出来。

2.1.2、字体颜色的设置

(1)基础版本中bar的颜色是默认色,这里我们需要对其进行修改。

p1 = ax.barh(x-0.2,Multicore ,height=width,color='#5A8FFF',label='多核')
p2 = ax.barh(x+0.2,Singlecore,height=width,color='#CEFD89',label='单核')

(2)同时,左侧的y轴的刻度标签字体,根据处理器品牌的不同也是不同的颜色。因此也需要进行处理。

#这里首先要重新定义一下名称列表,将芯片与对应型号分开
#目的是不再用yticks和yticklabels,而是用ax.text去实现。
name1 = ['麒麟9000S','华为Mate 60Pro','麒麟9000','华为Mate 40Pro','骁龙8 Gen2','小米13','骁龙8 Gen1','Moto edge X30','骁龙888','魅族18','骁龙865','一加8 Pro','天玑8100','红米K50']
for i in range(len(Multicore)):ax.text(-750,i-1.5*height,s=name1[0::2][i],va='top',ha='left',fontsize=12,color=colors[i],transform = ax.transData)ax.text(-750,i+0.5*height,s=name1[1::2][i],va='top',ha='left',fontsize=9,color='w',transform = ax.transData)

2.2 bar数值显示

这个直接用bar_label函数就可以啦

for p in [p1,p2]:ax.bar_label(p,color='w',padding=10)

上完整代码

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Microsoft Yahei'Multicore = np.array([4019,3770,5150,3830,3765,3395,3820])
Singlecore = np.array([1005,1019,1508,1255,1127,903,907])
name1 = ['麒麟9000S','华为Mate 60Pro','麒麟9000','华为Mate 40Pro','骁龙8 Gen2','小米13','骁龙8 Gen1','Moto edge X30','骁龙888','魅族18','骁龙865','一加8 Pro','天玑8100','红米K50']
x = np.arange(len(Multicore))height = 0.25colors=['r','r','lightskyblue','lightskyblue','lightskyblue','lightskyblue','orange']
fig,ax = plt.subplots(figsize=(12,5),facecolor='k')
ax.set_facecolor('k')p1 = ax.barh(x-0.2,Multicore ,height=height,color='#5A8FFF',label='多核')
p2 = ax.barh(x+0.2,Singlecore,height=height,color='#CEFD89',label='单核')for p in [p1,p2]:ax.bar_label(p,color='w',padding=10)ax.legend(frameon= False,labelcolor='w',loc=(0.9,0.98),ncol=2)
ax.invert_yaxis()
ax.set_xticks([])
ax.set_yticks([])
ax.set_xlim(-800,5400)
for i in range(len(Multicore)):ax.text(-750,i-1.5*height,s=name1[0::2][i],va='top',ha='left',fontsize=12,color=colors[i],transform = ax.transData)ax.text(-750,i+0.5*height,s=name1[1::2][i],va='top',ha='left',fontsize=9,color='w',transform = ax.transData)
plt.show()

显示结果

进阶版图片怎么样,是不是有点点像了捏?

3、高级版本

虽然实现了进阶版本,但是也是大面上实现了这样一个样式。仍然有些元素或者说细节没有实现。
抱着追求完美的态度,总结一下进阶版本仍然存在的问题:


1、bar的形状是带圆角的长方形,这个难以用bar函数实现
2、图形的上方有个炫酷的标题和一个logo


如何解决上述问题呢?

很遗憾,基础代码进阶代码的思路在这里可能用不了。为了实现这个功能,需要重新转换思路。

3.1 带圆角的bar

其实bar对象是class matplotlib.patches.Rectangle 的一个实例。那么圆角矩阵就对应class matplotlib.patches.FancyBboxPatch

for i in range(len(Multicore)):mcp.append(mpatches.FancyBboxPatch((0,i-1.5*height),Multicore[i],height,ec="none",color='#5A8FFF',boxstyle=mpatches.BoxStyle("Round4", pad=0.03)))scp.append(mpatches.FancyBboxPatch((0,i+0.5*height),Singlecore[i],height,ec="none",color='#CEFD89',boxstyle=mpatches.BoxStyle("Round4", pad=0.03)))ax.text(-0.4,i-1.5*height,s=name1[0::2][i],va='top',ha='left',fontsize=12,color=colors[i],transform = ax.transData)ax.text(-0.4,i+0.5*height,s=name1[1::2][i],va='top',ha='left',fontsize=9,color='w',transform = ax.transData)
for mp,sp in zip(mcp,scp):ax.add_artist(mp)

其中 MulticoreSinglecore 的数据都除以3000。原因就是FancyBboxPatch长宽比例差距过大的时候round几乎看不出来。

Multicore = np.array([4019,3770,5150,3830,3765,3395,3820])/3000
Singlecore = np.array([1005,1019,1508,1255,1127,903,907])/3000

3.2 标题和Logo

3.2.1 标题

废话不多说,直接上代码
>||<这个多边形的形状是我一点点找坐标调出来的,太费劲了 >||<

verts = [[-0.58,-2.3],[-0.32,-2.4],[-0.3, -2.2], [1.,   -2.2],  [0.98, -1.3], [0.95, -1.1],[-0.3, -1.1], [-0.3, -1.1],[-0.32,-0.9],[-0.52,-0.9],[-0.55,-1.1],[-0.52,-0.9],
]
# 坐标对应的路径代码
codes = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.CLOSEPOLY,
]
path1 = Path(verts, codes)
patch1 = mpatches.PathPatch(path1, facecolor='lightgrey', zorder=0,lw=2,alpha=0.7)
ax.add_patch(patch1)

3.2.2 Logo

由于Logo这个我没有现成的图片,不知道会不会涉及版权啥的,我就用一个自己电脑里的logo图标替代一下。

myfig = mpimg.imread(r'E:/Desktop/Logo.png')
axin = ax.inset_axes([0,0.85,0.12,0.12])
axin.imshow(myfig)
axin.set_axis_off()

我的logo
Logo

最终完整代码

上完整代码

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.path import Path
import matplotlib.image as mpimg
plt.rcParams['font.family'] = 'Microsoft Yahei'height= 0.2
mcp = []
scp = []
colors=['r','r','lightskyblue','lightskyblue','lightskyblue','lightskyblue','orange']
name1 = ['麒麟9000S','华为Mate 60Pro','麒麟9000','华为Mate 40Pro','骁龙8 Gen2','小米13','骁龙8 Gen1','Moto edge X30','骁龙888','魅族18','骁龙865','一加8 Pro','天玑8100','红米K50']
Multicore = np.array([4019,3770,5150,3830,3765,3395,3820])/3000
Singlecore = np.array([1005,1019,1508,1255,1127,903,907])/3000
x = np.arange(len(Multicore))fig,ax = plt.subplots(figsize=(12,6),facecolor='k',dpi=600)for i in range(len(Multicore)):mcp.append(mpatches.FancyBboxPatch((0,i-1.5*height),Multicore[i],height,ec="none",color='#5A8FFF',boxstyle=mpatches.BoxStyle("Round4", pad=0.03)))scp.append(mpatches.FancyBboxPatch((0,i+0.5*height),Singlecore[i],height,ec="none",color='#CEFD89',boxstyle=mpatches.BoxStyle("Round4", pad=0.03)))ax.text(-0.4,i-1.5*height,s=name1[0::2][i],va='top',ha='left',fontsize=12,color=colors[i],transform = ax.transData)ax.text(-0.4,i+0.5*height,s=name1[1::2][i],va='top',ha='left',fontsize=9,color='w',transform = ax.transData)
for mp,sp in zip(mcp,scp):ax.add_artist(mp)ax.add_artist(sp)
p1 = ax.barh(x-0.2,Multicore ,height=height,color='none')
p2 = ax.barh(x+0.2,Singlecore,height=height,color='none')
for p in [p1,p2]:ax.bar_label(p,labels=[int(np.round(i)) for i in p.datavalues*2000],color='w',padding=10)
ax.set_facecolor('k')ax.set_xlim(-0.6,2.)
ax.set_ylim(-2.5,6.5)
ax.set_xticks([])
ax.set_yticks([])
ax.invert_yaxis()myfig = mpimg.imread(r'E:/Desktop/Logo.png')
axin = ax.inset_axes([0,0.85,0.12,0.12])
axin.imshow(myfig)
axin.set_axis_off()
verts = [[-0.58,-2.3],[-0.32,-2.4],[-0.3, -2.2], [1.,  -2.2],  [0.98, -1.3], [0.95, -1.1],[-0.3, -1.1], [-0.3, -1.1],[-0.32,-0.9],[-0.52,-0.9],[-0.55,-1.1],[-0.52,-0.9],
]# 坐标对应的路径代码
codes = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.CLOSEPOLY,
]path1 = Path(verts, codes)
patch1 = mpatches.PathPatch(path1, facecolor='lightgrey', zorder=0,lw=2,alpha=0.7)
ax.add_patch(patch1)
ax.text(-0.2, -1.6,'Geekbench 5 CPU 测试',fontstyle='italic',color='w',va='center',ha='left',fontsize=20,fontweight='bold')
ax.legend(handles=[mp,sp],labels=['多核','单核'],frameon=False,labelcolor='w',ncol=2,loc=(0.78,0.84),fontsize=12,markerfirst=False)plt.show()

附图

高级版图片

已经十分相似了。哈哈哈哈!

不过仍然有两个小问题可以再进行优化:

1、legend中的矩形没有做到圆角。
2、bar的颜色没有改成渐变色。


欢迎小伙伴对代码进行优化和讨论!
也欢迎小伙伴向我进行咨询!


这篇关于用Matplotlib绘制柱状图(仿照极客湾的Mate60 Pro评测跑分图)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/191722

相关文章

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

售价599元起! 华为路由器X1/Pro发布 配置与区别一览

《售价599元起!华为路由器X1/Pro发布配置与区别一览》华为路由器X1/Pro发布,有朋友留言问华为路由X1和X1Pro怎么选择,关于这个问题,本期图文将对这二款路由器做了期参数对比,大家看... 华为路由 X1 系列已经正式发布并开启预售,将在 4 月 25 日 10:08 正式开售,两款产品分别为华

4G/5G全网通! FiberHome烽火5G CPE Air路由器拆机评测

《4G/5G全网通!FiberHome烽火5GCPEAir路由器拆机评测》烽火5GCPE已经使用一段时间了,很多朋友想要知道这款路由器怎么样?今天我们就来看看拆机测评... 我想大家都听说过、了解过5G。 5G是具有高速率、低时延和大连接特点的新一代宽带移动通信技术,5G通讯设施是实现人机物互联的网络基础设

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

Ubuntu 24.04 LTS怎么关闭 Ubuntu Pro 更新提示弹窗?

《Ubuntu24.04LTS怎么关闭UbuntuPro更新提示弹窗?》Ubuntu每次开机都会弹窗提示安全更新,设置里最多只能取消自动下载,自动更新,但无法做到直接让自动更新的弹窗不出现,... 如果你正在使用 Ubuntu 24.04 LTS,可能会注意到——在使用「软件更新器」或运行 APT 命令时,

最便宜的8口2.5G网管交换机! 水星SE109 Pro拆机测评

《最便宜的8口2.5G网管交换机!水星SE109Pro拆机测评》水星SE109Pro价格很便宜,水星SE109Pro,外观、接口,和SE109一样,区别Pro是网管型的,下面我们就来看看详细拆... 听说水星SE109 Pro开卖了,PDD卖 220元,于是买回来javascript拆机看看。推荐阅读:水

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math