最近有很多小伙伴私信我关于双Y轴图的绘制方法? 这里我就直接给出Python-matplotlib绘制方法和R-ggplot2的绘制方法,主要的知识点如下:
- Matplotlib-Axes.twinx()方法添加副轴
- ggplot2-sec.axis()绘制双轴
Matplotlib-Axes.twinx()方法添加副轴
这里我们直接就给出数据预览和可视化设计的代码,图中部分代码我们再做详细解释,数据预览如下:
自定义的颜色字典year_color构造代码如下:
代码语言:javascript复制color = ("#51C1C8", "#E96279", "#44A2D6", "#536D84",
"#51C1C8", "#E96279", "#44A2D6", "#536D84")
year = artist_01.index.to_list()
year_color = dict(zip(year,color))
year_color
可视化代码如下:
代码语言:javascript复制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. 添加横线(修饰)
代码语言:javascript复制ax.axhline(y=0,color='#45627C',lw=3)
2. 添加标题处小图
代码语言:javascript复制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()方法绘制:重点
代码语言:javascript复制#添加双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()属性设置。
构建数据
这里我们构建虚拟数据,代码如下:
代码语言:javascript复制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官网,代码如下:
代码语言:javascript复制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),
)
设置双轴代码:
代码语言:javascript复制 #设置双轴关键代码
scale_y_continuous(
# first axis name
name = "Temperature (C°)",
# 定制化设置第二个图例属性
sec.axis = sec_axis(trans = ~.*coeff, name="Price ($)")
)
最终可视化代码如下:
总结
本期推文我们简单介绍了Python-matplotlib和R-ggplot2 绘制双Y轴的绘制方法,希望可以帮助到有需要的小伙伴。我们基础系列的图表绘制教程还在继续中哦,感谢大家持续支持和关注。