绘图提高篇 | Python/R 双Y轴绘制

最近有很多小伙伴私信我关于双Y轴图的绘制方法? 这里我就直接给出Python-matplotlib绘制方法和R-ggplot2的绘制方法,主要的知识点如下:

  • Matplotlib-Axes.twinx()方法添加副轴

  • ggplot2-sec.axis()绘制双轴

  • 所有内容都已免费新增到我们的系统可视化课程中,有需要可以咨询呀!

Matplotlib-Axes.twinx()方法添加副轴

这里我们直接就给出数据预览和可视化设计的代码,图中部分代码我们再做详细解释,数据预览如下:

自定义的颜色字典year_color构造代码如下:

复制代码
color = ("#51C1C8", "#E96279", "#44A2D6", "#536D84",
         "#51C1C8", "#E96279", "#44A2D6", "#536D84")
year = artist_01.index.to_list()
year_color = dict(zip(year,color))
year_color

可视化代码如下:

复制代码
plt.style.use('fivethirtyeight')
fig,ax = plt.subplots(figsize=(8,4),dpi=200,facecolor='white',edgecolor='white')
ax.set_facecolor('white')

x = np.arange(0,len(artist_01),1)
y = artist_01['data01'].values

#绘制连接点的线
line = ax.plot(x,y,color='#333333',lw=1.,zorder=2)
#绘制不同散点图
scatter_out = ax.scatter(x,y,s=500,zorder=1,color='white',ec='grey',alpha=.7,lw=.5)
for i in artist_01.index.to_list():
    scatter = ax.scatter(x[i],y[i],s=180,zorder=3,ec='k',lw=.4,color=year_color[i])
scatter_in = ax.scatter(x,y,s=30,zorder=3,color="#333333")

#定制化绘制(设置图表风格)
ax.grid(color='gray',lw=.5,alpha=.5) #设置网格
ax.tick_params(left=False,bottom=False,labelbottom=False,labelsize=10,colors='gray')#设置刻度
ax.set_ylim(bottom=-3,top=43)#设置轴范围
ax.set_yticks(np.arange(0, 45, step=5)) #设置刻度标签
ax.set_xticks(np.arange(-.5, 8, step=.5))
#添加横线(修饰)
ax.axhline(y=0,color='#45627C',lw=3)
#添加数字标签
label_text = {"size":13,"color":"k",'weight':'semibold'}
for a,b in zip(x,y):
    ax.text(a, b+2.5, '%.0f' % b, ha='center', va= 'bottom',fontdict=label_text,color=year_color[a])
#设置轴脊(spine)
for spine in ['top','bottom','left','right']:
    ax.spines[spine].set_color("#FFFFFF") #设置颜色/set_visible()设置显示与否
for i in artist_01.index.to_list()[:3]:
    axins.scatter(x[i],y[i],s=80,color=year_color[i],zorder=2)
    
#添加标题处小图
#添加小散点图:重点掌握   
axins = inset_axes(ax, width=.4, height=.4,loc='upper left',
                   bbox_to_anchor=(0.01, 0.22, 1, 1),
                   bbox_transform=ax.transAxes,
                   borderpad=0)
axins.set_ylim(bottom=8,top=35)
axins.set_xlim(left=-.5,right=2.5)
axins.plot(x[:3],y[:3],color='#333333',lw=1.,zorder=1)
for i in artist_01.index.to_list()[:3]:
    axins.scatter(x[i],y[i],s=80,color=year_color[i],zorder=2)
axins.axis('off')
#绘制小横线:原理同上
line = inset_axes(ax,width=5.3, height=.4,loc='upper left',
                  bbox_to_anchor=(-0.015, 0.15, 1, 1),
                  bbox_transform=ax.transAxes,
                  borderpad=0)
line.plot([.1,.7],[.1,.1],color='#45627C',lw=2)
line.axis('off')

#添加阴影效果
for i in artist_01.index.to_list():
    ax.axvspan(i-.35, i+.35, facecolor='gray',alpha=.1,zorder=0)
    
#添加双y轴:使用Axes.twinx()方法绘制
second_plot = ax.twinx()
second_plot.set_ylim(bottom=-3,top=43)
second_plot.set_yticks(np.arange(0, 50, step=10))
second_plot.set_xticks(np.arange(-.5, 8, step=.5))
second_plot.tick_params(left=False,bottom=False,labelbottom=False,labelsize=10,colors='k')
second_plot.grid(color="none",zorder=0)
second_plot.set_axisbelow(True)
for spine in ['top','bottom','left','right']:
    second_plot.spines[spine].set_visible(False) #("#FFFFFF")

y2 = artist_01['data02'].values
label_text = {"size":28,"color":"white",'weight':'light'}
for x,y2 in zip(np.arange(len(artist_01)).tolist(),artist_01['data02'].to_list()):
    second_plot.plot([x,x],[0,y2],lw=20,color=color[x],solid_capstyle='round')
    #绘制空心圆
    second_plot.scatter(x,0,s=150,c='white',zorder=3)
    second_plot.scatter(x,0,s=60,c=color[x],zorder=4)
    second_plot.scatter(x,0,s=15,c='white',zorder=5)
   
# 添加文本信息
label_font = {"size":15,'weight':'bold'}
for i,x,text in zip(artist_01.index.to_list(),np.arange(0,len(artist_01),1),artist_01['year'].values):
    ax.text(x, -8,text ,ha='center', va= 'bottom',fontdict=label_font,color=year_color[i],zorder=2)

ax.text(.39,1.2,'\nSecond Y Axes Plot Exercise',transform = ax.transAxes,
        ha='center', va='center',fontsize = 20,color='k',fontweight="bold")
ax.text(.02,1.04,'Use the Matplotlib axes.Axes.twinx()',
        transform = ax.transAxes,
        ha='left', va='center',fontsize = 9,color='#45627C')

ax.text(.91,.02,'\nVisualization by DataCharm',transform = ax.transAxes,
        ha='center', va='center',fontsize = 7,color='black')
plt.savefig(r'double_y_axis_plot.png',width=6,height=3,
            dpi=900,bbox_inches='tight',facecolor='white')
#ax.set_axisbelow(True)
plt.show()

解释:

1. 添加横线(修饰)

复制代码
ax.axhline(y=0,color='#45627C',lw=3)

2. 添加标题处小图

复制代码
axins = inset_axes(ax, width=.4, height=.4,loc='upper left',
                   bbox_to_anchor=(0.01, 0.22, 1, 1),
                   bbox_transform=ax.transAxes,
                   borderpad=0)
axins.set_ylim(bottom=8,top=35)
axins.set_xlim(left=-.5,right=2.5)
axins.plot(x[:3],y[:3],color='#333333',lw=1.,zorder=1)
for i in artist_01.index.to_list()[:3]:
    axins.scatter(x[i],y[i],s=80,color=year_color[i],zorder=2)
axins.axis('off')

3. 添加双y轴:使用Axes.twinx()方法绘制:重点

复制代码
#添加双y轴:使用Axes.twinx()方法绘制
second_plot = ax.twinx()
second_plot.set_ylim(bottom=-3,top=43)
second_plot.set_yticks(np.arange(0, 50, step=10))
second_plot.set_xticks(np.arange(-.5, 8, step=.5))
second_plot.tick_params(left=False,bottom=False,labelbottom=False,labelsize=10,colors='k')
second_plot.grid(color="none",zorder=0)
second_plot.set_axisbelow(True)
for spine in ['top','bottom','left','right']:
    second_plot.spines[spine].set_visible(False) #("#FFFFFF")

y2 = artist_01['data02'].values
label_text = {"size":28,"color":"white",'weight':'light'}
for x,y2 in zip(np.arange(len(artist_01)).tolist(),artist_01['data02'].to_list()):
    second_plot.plot([x,x],[0,y2],lw=20,color=color[x],solid_capstyle='round')
    #绘制空心圆
    second_plot.scatter(x,0,s=150,c='white',zorder=3)
    second_plot.scatter(x,0,s=60,c=color[x],zorder=4)
    second_plot.scatter(x,0,s=15,c='white',zorder=5)

最终的可视化结果如下:

总结: Python-matplotlib 绘制双Y轴的关键就是使用Axes.twinx()方法 再次添加一个绘图对象,再把要绘制的对象在此绘图对象上绘制即可,其他和正常的matplotlib语法一样。

ggplot2-sec.axis()绘制双轴

在介绍完Python-matplotlib 绘制双Y轴后,我们再次介绍R-ggplot2如何绘制双Y轴,由于绘制上面的可视化结果较为繁琐,这里我们直接生成样例数据进行双Y轴的讲解。主要涉及的知识点就是scale_y_continuous() 或scale_x_continuous()中的sec.axis()属性设置。

构建数据

这里我们构建虚拟数据,代码如下:

复制代码
data <- data.frame(
  day = as.Date("2019-01-01") + 0:99,
  temperature = runif(100) + seq(1,100)^2.5 / 10000,
  price = runif(100) + seq(100,1)^1.5 / 10
)
head(data)

数据预览如下(部分):

可视化绘制

这里我们直接给出代码,大家不懂的可以参考ggplot2官网,代码如下:

复制代码
coeff <- 10
temperatureColor <- "#75B8D1"
priceColor <- "#D175B8"

double_y <-ggplot(data, aes(x=day)) +
 geom_line(aes(y=temperature), size=1.5, color=temperatureColor) + 
 geom_line(aes(y=price / coeff), size=1.5, color=priceColor) +
 #设置双轴关键代码
 scale_y_continuous(
   # first axis name
   name = "Temperature (C°)",
   # 定制化设置第二个图例属性
   sec.axis = sec_axis(trans = ~.*coeff, name="Price ($)")
 ) + 
 labs(x="",
      title = "R Charts Exercise: <span style='color:#D20F26'>Double Y Axis</span>",
      subtitle = "processed charts with <span style='color:#1A73E8'>scale_y/x_continuous:sec_axis()</span>",
      caption = "Visualization by <span style='color:#DD6449'>DataCharm</span>") +
 theme_ft_rc()+
 theme(
   axis.title.y = element_text(color = temperatureColor, size=13),
   axis.title.y.right = element_text(color = priceColor, size=13),
   plot.title = element_markdown(hjust = 0.5,vjust = .5,color = "black",
                                 size = 20, margin = margin(t = 1, b = 12)),
   plot.subtitle = element_markdown(hjust = 0,vjust = .5,size=15),
   plot.caption = element_markdown(face = 'bold',size = 12),
 ) 

设置双轴代码:

复制代码
 #设置双轴关键代码
 scale_y_continuous(
   # first axis name
   name = "Temperature (C°)",
   # 定制化设置第二个图例属性
   sec.axis = sec_axis(trans = ~.*coeff, name="Price ($)")
 ) + 

最终可视化代码如下:

总结

本期推文我们简单介绍了Python-matplotlibR-ggplot2 绘制双Y轴的绘制方法,希望可以帮助到有需要的小伙伴。我们基础系列的图表绘制教程还在继续中哦,感谢大家持续支持和关注。

相关推荐
天水幼麟1 分钟前
python学习笔记(深度学习)
笔记·python·学习
巴里巴气4 分钟前
安装GPU版本的Pytorch
人工智能·pytorch·python
「、皓子~13 分钟前
后台管理系统的诞生 - 利用AI 1天完成整个后台管理系统的微服务后端+前端
前端·人工智能·微服务·小程序·go·ai编程·ai写作
wt_cs25 分钟前
银行回单ocr api集成解析-图像文字识别-文字识别技术
开发语言·python
_WndProc1 小时前
【Python】Flask网页
开发语言·python·flask
笑衬人心。1 小时前
初学Spring AI 笔记
人工智能·笔记·spring
互联网搬砖老肖1 小时前
Python 中如何使用 Conda 管理版本和创建 Django 项目
python·django·conda
luofeiju1 小时前
RGB下的色彩变换:用线性代数解构色彩世界
图像处理·人工智能·opencv·线性代数
测试者家园1 小时前
基于DeepSeek和crewAI构建测试用例脚本生成器
人工智能·python·测试用例·智能体·智能化测试·crewai
liujing102329291 小时前
Day04_刷题niuke20250703
java·开发语言·算法