以下の投稿の後、matplotlib.table
のデザインをいじってみたので紹介する。
(0)edges='open'
での出力(装飾なし)
(1)縦横罫線の表
(2)横罫線のみの表
(3)罫線を用いず行を色分けした表
プログラム
import openpyxl as excel
import matplotlib.pyplot as plt
import numpy as np
def inp_excel(fnameR):
book=excel.load_workbook(fnameR,data_only=True)
worksheet=book['data']
srmax,scmax=50,10 # search range
k=0
sr=[]
for i in range(0,srmax):
nrow=i+1
ss=worksheet.cell(row=nrow,column=1).value
if ss==None: k=k+1
if k<3: sr.append(ss)
if k==3: break
n=len(sr)
k=0
sc=[]
for j in range(0,scmax):
ncol=j+1
ss=worksheet.cell(row=2,column=ncol).value
if ss==None: k=k+1
if k<1: sc.append(ss)
if k==1: break
m=len(sc)
rstr=f'A1:{chr(64+m)}{n}'
rect=worksheet[f'{rstr}']
data=[]
for row in rect:
row_data=[]
for cell in row:
s=cell.value
if s==None: s1=''
else:
try:
s=float(s)
s1=np.round(s,decimals=3)
except ValueError:
s1=s
row_data.append(s1)
data.append(row_data)
data=np.array(data,dtype=object)
return data
def make_sdata(data):
# change to str data
n,m=data.shape
sdata=np.empty((n,m),dtype=object)
for i in range(n):
for j in range(m):
s=data[i,j]
if s=='': s1=''
else:
try:
s=float(s)
s1=f'{s:.3f}'
except ValueError:
s1=s
sdata[i,j]=s1
return sdata
def cells_1(sdata,tbl,trow):
n,m=sdata.shape
for i in range(n):
for j in range(m):
if sdata[i,j]!='':
# alignment of title of each sub-table
if i==trow[0] or i==trow[1] or i==trow[2]:
tbl[i,j].set_text_props(ha='left',weight='bold')
# color of each cell
if i!=trow[0] and i!=trow[1] and i!=trow[2]:
tbl[i,j].visible_edges='closed'
tbl[i,j].set_linewidth(0.5)
# header color of each sub-table
if i==trow[0]+1 or i==trow[1]+1 or i==trow[2]+2:
tbl[i,j].visible_edges='closed'
tbl[i,j].set_linewidth(0.5)
tbl[i,j].set_facecolor('#dddddd')
def cells_2(sdata,tbl,trow):
n,m=sdata.shape
for i in range(n):
for j in range(m):
if sdata[i,j]!='':
# alignment of title of each sub-table
if i==trow[0] or i==trow[1] or i==trow[2]:
tbl[i,j].set_text_props(ha='left',weight='bold')
# line of each row
if i!=trow[0] and i!=trow[1] and i!=trow[2]:
tbl[i,j].visible_edges='TB'
tbl[i,j].set_linewidth(0.5)
tbl[i,j].set_edgecolor('#000066')
# header color of each sub-table
if i==trow[0]+1 or i==trow[1]+1 or i==trow[2]+2:
tbl[i,j].visible_edges='closed'
tbl[i,j].set_linewidth(0)
tbl[i,j].set_text_props(color='#ffffff')
tbl[i,j].set_facecolor('#000066')
def cells_3(sdata,tbl,trow):
n,m=sdata.shape
for i in range(n):
for j in range(m):
if sdata[i,j]!='':
# alignment of title of each sub-table
if i==trow[0] or i==trow[1] or i==trow[2]:
tbl[i,j].set_text_props(ha='left',weight='bold')
# color of each cell
if i!=trow[0] and i!=trow[1] and i!=trow[2]:
if i%2==0: col='#fffacd'
else: col='#f5deb3'
tbl[i,j].visible_edges='closed'
tbl[i,j].set_linewidth(0)
tbl[i,j].set_facecolor(col)
# header color of each sub-table
if i==trow[0]+1 or i==trow[1]+1 or i==trow[2]+2:
tbl[i,j].visible_edges='closed'
tbl[i,j].set_linewidth(0)
tbl[i,j].set_text_props(color='#ffffff')
tbl[i,j].set_facecolor('#864a2b')
def fig(nnn,fnameR,fnameF):
data=inp_excel(fnameR)
sdata=make_sdata(data)
n,m=sdata.shape
trow=[]
for i in range(n):
if sdata[i,0]=='Data for basic design': trow.append(i)
if sdata[i,0]=='Data for surging analysis': trow.append(i)
if sdata[i,0]=='Shaft data': trow.append(i)
i,j=trow[2]+1,2; sdata[i,j]=f'{data[i,j]:.0f}'
tstr='Surging analysis data'
astr=' (matplotlib.table)'
tstr=tstr+astr
tw,th=1,1
col=np.array([2.0, 0.8, 0.8]+[1]*(m-3))
colw=col/np.sum(col)*tw
fsz=7.5
xmin,xmax=0,1
ymin,ymax=0,1
iw,ih=10, 12 # default (inch)
plt.figure(figsize=(iw,ih),facecolor='w')
plt.xlim([xmin,xmax])
plt.ylim([ymin,ymax])
plt.axis('off')
tbl=plt.table(
cellText=sdata,
colWidths=colw,
cellLoc='center',
edges='open',
bbox=[xmin,ymin,tw,th]
)
# fontsize change
tbl.auto_set_font_size(False)
tbl.set_fontsize(fsz)
# decoration of cells
if nnn==1: cells_1(sdata,tbl,trow)
if nnn==2: cells_2(sdata,tbl,trow)
if nnn==3: cells_3(sdata,tbl,trow)
plt.title(tstr,x=np.sum(colw[0:m])/2,fontsize=fsz+2,weight='bold')
plt.savefig(fnameF, dpi=200, bbox_inches="tight", pad_inches=0.1)
#plt.show()
def main():
#fnameR='surge_data_TR.xlsx'
#fnameR='surge_data_HR_1.xlsx'
fnameR='surge_data_HR_2.xlsx'
for nnn in [0,1,2,3]:
fnameF=f'fig_test{nnn}.jpg'
fig(nnn,fnameR,fnameF)
#---------------
# Execute
#---------------
if __name__ == '__main__': main()
感想
エクセルの表をいじらなくてもpython
側の表作成過程で色々デザインをいじれて楽しい。
以 上