大家在读论文的时候有没有遇到过这种类似实验图,尤其是这种带有label的自己又不会做。我不知道大家在做论文图片的时候用的是什么软件啊,可能有的用的drawio,有的用origin。但是呢,这种图其实用python中的pyplot库就能简单完成了,而且可以保证300dpi等等格式等等,我今天会把pyplot的一些细节都讲到!,ok,上码!
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
from PIL import Image
plt.rcParams["font.family"] = 'Arial'
k = np.arange(5)
x = ['4','12','24','48','96']
A = [1.0757 , 1.8956 , 2.2976 , 2.5995 , 2.7100 ]
B = [1.1859,1.9832, 2.2188,2.5299,2.5815]
C = [1.1060 , 1.8936 , 2.2103 , 2.5145 , 2.5519]
D = [1.1026 , 1.8324 , 2.1805 , 2.5395, 2.5628 ]
E = [0.9670 , 1.6270 , 2.0213 , 2.4263 , 2.5145]
F = [0.9552 , 1.5940 , 1.9316 , 2.0840 , 2.1700]
fontsize = 15
w = 5.0
h = w / 2.75
plt.figure(figsize = (w,h),dpi = 300)
plt.subplot(111)
total_width, n = 0.7, 6 #设置宽度和实例个数
width = total_width / n
plt.bar(k, A, width=width, label='A_model')
plt.bar(k+ 1*width, B, width=width, label='B_model',tick_label = x)
plt.bar(k+ 2*width, C, width=width, label='C_model',tick_label = x)
plt.bar(k+ 3*width, D, width=width, label='D_model',tick_label = x)
plt.bar(k+ 4*width, E, width=width, label='E_model',tick_label = x)
plt.bar(k+ 5*width, F, width=width, label='F_model',tick_label = x)
plt.xticks(k + 5 * width / 2,x)
plt.ylim(0,3.2)
plt.title('Fig1', fontsize = fontsize)
plt.ylabel('y')
plt.xlabel('x')
plt.legend(ncol=1, bbox_to_anchor=(1.15,0), loc='lower center', edgecolor='w')
plt.savefig('Fig1.jpg', dpi=300,bbox_inches='tight')
fig1 = Image.open('Fig1.jpg')
w, h = fig1.size
print(w/h)
运行结果:
2.506787330316742,下面是图片,我发的期刊格式要求长宽比2.5,这里看各位需求
下面是图片的属性,大家可以看一下dpi也是300哦,dpi根据自己需求设定。
注意:plt.figure(figsize = (w,h),dpi = 300)这里的dpi和plt.savefig(‘Fig1.jpg’, dpi=300,bbox_inches=‘tight’)这里的dpi最好保持一致
这里主要是通过这个函数
plt.legend(ncol=1, bbox_to_anchor=(1.15,0), loc=‘lower center’, edgecolor=‘w’)
ncol表示显示label的一行有几个,例如我设为1,就是纵向排列,这个看你自己的设计观念,再举个例子,把ncol设成2,如下,理解了吧!
那大家可以看到设成2是不是和柱状图重叠了一部分,这时候就需要自己调了。
怎么调呢,先设loc,loc是label的主要位置,lower center就是柱状图中下的位置,其他种类自己查啊。设完loc在设bbox_to_anchor,bbox_to_anchor是可以具体调位置的,很细!bbox_to_anchor是在你先前设的loc位置的基础上去平移的。
bbox_to_anchor(x,y):x表示横向平移,正数向右负数向左,y表示纵向平移,正数向上负数向下
我要的是宽比高是2.5,为什么这给了个2.75???
w = 5.0
h = w / 2.75
因为plt.figure(figsize = (w,h),dpi = 300)这里figsize是你的画布大小,而因为你把legend设在外边了所以外面legend超出画布了,自己也占像素了,懂不懂?
那我怎么知道这里设多少,2.75?我是慢慢枚举的啊,慢慢测呗。
初始的w可以自己设定,但最好不要设的太大,设得太大出来的图片像素值也大,后期在缩放,效果可能不会好
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
from PIL import Image
plt.rcParams["font.family"] = 'Arial'
w = 10
h = w / 4.85
plt.figure(figsize = (w,h),dpi = 300)
fig = plt.figure(figsize = (w,h))
plt.subplot(111)
plt.plot(A, label = "A")
plt.plot(B, label = "B")
plt.plot(C, label = "C")
plt.plot(D, label = "D")
plt.plot(E, label = "E")
plt.plot(F, label = "F")
fontsize = 17
plt.xticks(fontsize = fontsize)
plt.yticks(fontsize = fontsize)
plt.title('Fig2', fontsize = fontsize)
plt.xlabel('x', fontsize = fontsize)
plt.ylabel('y', fontsize = fontsize)
plt.legend(ncol=4, bbox_to_anchor=(0.5,-1), loc='lower center', edgecolor='w', fontsize = fontsize)
plt.savefig('Fig2.jpg', dpi=300,bbox_inches='tight')
fig1 = Image.open('Fig2.jpg')
w, h = fig1.size
print(w/h)
运行结果:
2.508704061895551,折线和柱状图同理就不解释了,这里设了一个ncol=4,可以看一下差别。
下面是属性,是不是把w设大,图片像素值就大了
补充:
plt.savefig(‘Fig2.jpg’, dpi=300,bbox_inches=‘tight’)
bbox_inches='tight’可以避免图像保存不全的问题。