用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绘制蛇年春节祝福艺术图

《使用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

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

免费也能高质量!2024年免费录屏软件深度对比评测

我公司因为客户覆盖面广的原因经常会开远程会议,有时候说的内容比较广需要引用多份的数据,我记录起来有一定难度,所以一般都用录屏工具来记录会议内容。这次我们来一起探索有什么免费录屏工具可以提高我们的工作效率吧。 1.福晰录屏大师 链接直达:https://www.foxitsoftware.cn/REC/  录屏软件录屏功能就是本职,这款录屏工具在录屏模式上提供了多种选项,可以选择屏幕录制、窗口

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87