φυβλαςのβλογ
phyblas的博客



numpy & matplotlib เบื้องต้น บทที่ ๙: การปรับแต่งแกนกราฟ
เขียนเมื่อ 2016/06/11 17:11
แก้ไขล่าสุด 2022/07/21 20:18
แกนของกราฟเป็นสิ่งที่มีความสำคัญเพราะทำหน้าที่บอกพิกัด เราสามารถปรับเปลี่ยนแกนกราฟได้ตามที่ต้องการมากมาย



การใส่เส้นกริด
เพื่อจะให้เห็นตำแหน่งอะไรต่างๆในกราฟชัดเจน บางทีสิ่งที่จำเป็นอีกอย่างก็คือเส้นกริด

การใส่เส้นกริดทำได้โดยใช้ฟังก์ชัน plt.grid หรือใช้เมธอด grid ทำกับตัว axes
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-20,20,500)
y = 2*np.sin(x)+x/2
plt.plot(x,y,c='#111111')
plt.grid()
plt.show()



ถ้าไม่ได้ใส่คีย์เวิร์ดอะไรลงไปก็จะได้เส้นประสีดำ แต่เราสามารถปรับแต่งได้ด้วยการใส่คีย์เวิร์ดลงไป โดยใส่ได้ทั้งชื่อเต็มและย่อ
color c สี
linestyle ls รูปแบบเส้น
linewidth lw ความหนาเส้น

ตัวอย่าง
theta = np.radians(np.linspace(0,720,1000))
r = np.sin(theta*5.5)
x = r*np.cos(theta)
y = r*np.sin(theta)
plt.figure(figsize=(6,6))
ax = plt.axes(facecolor='#FFEEFF')
ax.plot(x,y,c='#11AA99',lw=2)
ax.grid(c='#EE3388', ls='-', lw=2)
plt.show()





การเปลี่ยนกราฟเป็น log
ปกติกราฟที่เราวาดถ้าหากไม่ได้ตั้งอะไรจะมีการจัดเรียงเป็นเชิงเส้น แต่ก็สามารถทำเป็นลอการิธึมได้ด้วย การตั้งคีย์เวิร์ด xscale และ yscale ในตอนที่สร้าง axes

ตัวอย่าง
x = np.linspace(0,5,1000)
y = 5+5*np.sin(x*50)+np.exp(x)
yticks = np.linspace(0,160,9)
yticklabels = ['%d'%s for s in yticks]
plt.figure(figsize=(6,6))
ax = plt.axes(facecolor='#EEFFEE',yscale='log',yticks=yticks,yticklabels=yticklabels)
ax.plot(x,y,c='#11AA99',lw=2)
ax.grid(c='#EE3322', ls='-.', lw=1.5)
plt.show()



ซึ่งกราฟนี้ถ้าเขียนด้วยแกนธรรมดาจะเป็นแบบนี้
x = np.linspace(0,5,1000)
y = 5+5*np.sin(x*50)+np.exp(x)
plt.figure(figsize=(6,6))
ax = plt.axes(facecolor='#EEFFEE')
ax.plot(x,y,c='#11AA99',lw=2)
ax.grid(c='#EE3322', ls='-.', lw=1.5)
plt.show()



จะปรับค่าภายหลังโดยใช้ set_xscale('log') และ set_yscale('log') ก็ได้เช่นกัน

นอกจากนี้ยังมีอีกวิธีคือไม่ต้องไปใส่คีย์เวิร์ดภายในฟังก์ชัน plt.axes แต่แค่ให้แทนที่ตรงส่วนของฟังก์ชัน plot ด้วยฟังก์ชัน semilogy สำหรับการทำให้แกน y เป็นกราฟลอการิธึม หรือใช้ similogx เพื่อทำให้แกน x เป็นลอการิธึม แต่ถ้าต้องการให้เป็นกราฟลอการิธึมทังสองแกนก็ใช้ฟังก์ชัน loglog

ตัวอย่าง
x = np.linspace(0,5,1000)
y = 5+5*np.sin(x*50)+np.exp(x)
plt.axes(aspect=1)
plt.loglog(x,y,c='#AA7799',lw=2)
plt.grid(c='#555522', ls='-.', lw=1.5)
plt.show()



จะเห็นว่าการใช้ฟังก์ชัน semilogx, semilogy และ loglog ก็ทำให้ได้กราฟลอการิธึมเช่นกัน จะเลือกใช้วิธีไหนก็แล้วแต่สะดวก ความจริงแล้วการใช้ semilogx ก็เหมือนกับเป็นการใช้ plot แล้วตามด้วย set_xscale('log') ทันทีนั่นเอง



การกลับด้านแกน x และ y
หากปกติ y บวกอยู่บน ลบอยู่ล่าง x บวกอยู่ขวา ลบอยู่ซ้าย แต่เราสามารถทำให้มันสลับกันได้ด้วยเมธอด invert_xaxis และ invert_yaxis ของ axes

ตัวอย่าง
x = np.linspace(0,5,1000)
y = 15+15*np.sin(x*50)+np.exp(x)
ax = plt.axes(facecolor='#EEFFEE')
ax.plot(x,y,c='#FFAA00',lw=3)
ax.invert_yaxis()
ax.invert_xaxis()
plt.show()





การปรับแต่งขีดและเลขบอกค่า
ขีดและเลขบอกค่าสามารถปรับให้เป็นรูปแบบตามที่ต้องการได้โดยใช้ฟังก์ชัน plt.tick_params หรือใช้เป็นเมธอดบนออบเจ็กต์ axes

คีย์เวิร์ดที่ใช้ได้
axis กำหนดว่าเป็นการตั้งค่าให้แกนไหน ถ้าไม่ระบุจะมีผลทั้งแกน x และ y
which กำหนดว่าจะทำที่ขีดหลักหรือขีดย่อย (รายละเอียดอ่านบทที่ ๓๗)
pad ระยะห่างระหว่างตัวเลขและแกน ถ้าใส่ค่าบวกจะออกห่างไปด้านนอก ถ้าค่าเป็นลบจะเข้าด้านใน
labelsize ขนาดของตัวเลข
colors สีของตัวเลขและขีด
direction กำหนดว่าเส้นขีดจะอยู่ด้านในหรือด้านนอก 'in' ด้านใน 'out' ด้านนอก 'inout' ทั้งคู่
labelcolor สีของตัวเลข ถ้าไม่ได้กำหนดจะเหมือนสีขีด
width ความกว้างของเส้นขีด
length ความยาวของเส้นขีด
bottom, top, left, right ตั้งว่าจะแสดงเส้นขีดในด้านนั้นหรือไม่ ค่าใส่เป็น 1 (True) กับ 0 (False) ค่าตั้งต้นจะแสดงแค่ซ้ายและล่าง ส่วนด้านขวาและบนไม่แสดง
labelbottom, labeltop, labelleft, labelright ตั้งว่าจะแสดงข้อความในด้านนั้นหรือไม่ ค่าใส่เป็น 1 (True) กับ 0 (False) ค่าตั้งต้นจะแสดงแค่ซ้ายและล่าง ส่วนด้านขวาและบนไม่แสดง

ตัวอย่าง
x = np.linspace(-5,5,1000)
y = (20*np.sin(x*10)+10)*np.exp(x/4)
plt.figure(figsize=(6,6),facecolor='w')
ax = plt.axes(facecolor='#FFFEEE')
ax.plot(x,y,c='#11AA99',lw=2)
ax.tick_params(colors='#11AA11',labelsize=18,bottom=0,width=2.5,length=24) # ปรับทั้งสองแกน
ax.tick_params(axis='x',pad=-120,labelcolor='b') # ปรับเพิ่มเติมเฉพาะแกน x
ax.tick_params(axis='y',labelcolor='r',direction='inout') # ปรับเพิ่มเติมเฉพาะแกน y
plt.show()





การย้ายตำแหน่งเลขบอกค่าบนแกน
ปกติแล้วตัวเลขบอกค่าแกน x จะอยู่ด้านล่าง และ y จะอยู่ด้านซ้าย แต่ก็สามารถเปลี่ยนได้

คุณสมบัติต่างๆของแกน x และ y จะถูกเก็บอยู่ในออบเจ็กต์ชื่อ xaxis และ yaxis ซึ่งเป็นแอตทริบิวต์หนึ่งของ axes หากเราปรับค่าอะไรต่างๆที่ออบเจ็กต์นั้นการแสดงผลของแกนจะเปลี่ยนไป

การเปลี่ยนตำแหน่งของเลขบอกค่าแกนทำได้โดยใช้เมธอด set_ticks_position ของ xaxis และ yaxis

สำหรับ xaxis เลือกได้เป็น top กับ bottom ค่าตั้งต้นเป็น bottom
สำหรับ yaxis เลือกได้เป็น left กับ right ค่าตั้งต้นเป็น left

ลองดูตัวอย่างการปรับเลขบอกค่าไปอยู่ด้านบนและขวา
x = np.linspace(-5,5,1000)
y = (20*np.sin(x*10)+10)+x**2
ax = plt.axes(xlabel='x',ylabel='y',facecolor='#EFEEFE')
ax.plot(x,y,c='#77AA22')
ax.tick_params(labelsize=14,direction='inout',width=2.5,length=24)
ax.xaxis.set_ticks_position('top')
ax.yaxis.set_ticks_position('right')
plt.show()



นอกจากนี้ผลจากการใช้ set_ticks_position ยังทำให้เส้นขีดเหลืออยู่แค่ตำแหน่งที่เลือกเท่านั้นด้วย เช่นพอตั้งเป็น top กับ right แล้วเส้นขีดที่ฝั่งซ้ายกับล่างก็หายไป

ดังนั้นหากตั้งเป็น left กับ bottom ก็จะเป็นการลบเส้นขีดด้านขวากับบนไปด้วย



การย้ายชื่อแกน
เช่นเดียวกับตำแหน่งเลขบอกค่า ตำแหน่งของชื่อแกนก็สามารถย้ายได้ในลักษณะเดียวกัน โดยใช้เมธอด set_label_position ที่ xaxis และ yaxis

สำหรับ xaxis เลือกได้เป็น top กับ bottom ค่าตั้งต้นเป็น bottom
สำหรับ yaxis เลือกได้เป็น left กับ right ค่าตั้งต้นเป็น left

ตัวอย่าง
x = np.linspace(-5,5,2000)
y = (20*np.sin(x*10)+10)+x**2
ax = plt.axes(facecolor='#EFEEFE')
ax.set_xlabel('x',fontsize=14)
ax.set_ylabel('$(20\\sin(10x)+10)+x^2$',fontsize=14)
ax.plot(x,y,c='#77AA22')
ax.tick_params(labelsize=14,direction='inout',length=12)
ax.xaxis.set_label_position('top')
ax.yaxis.set_label_position('right')
plt.show()



แต่ถ้าต้องการปรับตำแหน่งให้เป็นไปตามที่ต้องการอย่างอิสระก็ใช้เมธอด set_label_coords โดยใส่พิกัดตำแหน่งที่ต้องการวางลงไป ตำแหน่งแนวนอนไล่จากซ้ายสุดของกราฟเป็น 0 ไปจนขวาสุดเป็น 1 แนวตั้งไล่จากล่างไปบนเป็น 0 ถึง 1

ตัวอย่าง
x = np.linspace(-5,5,2000)
y = 20+20*np.sin(x*10)+(x**2)*np.exp(x/10)
ax = plt.axes(facecolor='#EFEEFE')
ax.set_xlabel('$x$',fontsize=14)
ax.set_ylabel(r'$20+20\sin(10x)+x^2e^{\frac{x}{10}}$',fontsize=14,rotation=-90)
ax.plot(x,y,c='#77AA22')
ax.tick_params(labelsize=14,direction='inout',length=10)
ax.xaxis.set_label_coords(1.05, -0.05)
ax.yaxis.set_label_coords(1.02, 0.5)
plt.show()



อนึ่ง ตำแหน่งชื่อแกน x และ y นั้นที่จริงอาจตั้งโดยใส่ค่าเป็นคีย์เวิร์ดใน set_xlabel และ set_ylabel ดังที่ได้กล่าวไปในบทที่แล้วก็ได้เช่นกัน ส่วนการใช้ set_label_coords นี้ก็เป็นอีกทางเลือกหนึ่ง



การย้ายตำแหน่งเส้นแกน
โดยปกติแล้วเส้นแกนจะอยู่ที่ขอบบนล่างซ้ายขวา ๔ เส้น ทั้ง ๔ เส้นนี้เป็นออบเจ็กต์ที่เป็นแอตทริบิวต์หนึ่งของ axes

ออบเจ็กต์แกนทั้ง ๔ เก็บอยู่ในแอตทริบิวต์ชื่อ splines โดยแบ่งออกเป็น ๔ ตัวคือ
spines['top'] เส้นด้านบน
spines['bottom'] เส้นด้านล่าง
spines['left'] เส้นด้านซ้าย
spines['right'] เส้นด้านขวา

ตำแหน่งของเส้นแกนสามารถย้ายได้ด้วยเมธอด set_position

เมธอดนี้ต้องการอาร์กิวเมนต์เป็นคู่อันดับ (ทูเพิลหรือลิสต์) โดยเขียนเป็น (ชนิดตำแหน่ง, ค่าตำแหน่ง)
ชนิดตำแหน่งแบ่งออกเป็น ๓ ชนิดขึ้นอยู่กับว่าจะอ้างอิงอะไร
outward ระยะห่างจากขอบของกราฟ ถ้าค่าบวกจะไกลออกไป ถ้าค่าลบจะเข้ามาด้านใน
axes อ้างอิงตำแหน่งบนฉาก โดยไล่ตั้งแต่ 0 ถึง 1
data อ้างอิงตามค่า x และ y ในกราฟ

ลองยกตัวอย่างด้วยการวาดกราฟที่มีจุดศูนย์กลางอยู่ที่ตำแหน่ง (0,0) เราต้องการให้แกนมาอยู่
theta = np.radians(np.linspace(0,360,5000))
r = 2.5+np.sin(theta*110)+np.sin(theta*120)
x = r*np.cos(theta)
y = r*np.sin(theta)
plt.figure(figsize=(6,6))
ax = plt.axes(facecolor='#FFFFDD')
ax.plot(x,y,c='#FF5511')
ax.tick_params(labelsize=18,direction='inout')
ax.spines['bottom'].set_position(('data',0)) # ย้ายเส้นแกนซ้ายมาตรงกลาง
ax.spines['left'].set_position(('data',0)) # ย้ายเส้นแกนซ้ายมาตรงกลาง
ax.spines['right'].set_visible(0) # ซ่อนเส้นแกนขวา
ax.spines['top'].set_visible(0) # ซ่อนเส้นแกนบน
plt.show()



ในที่นี้มีการใช้เมธอด set_visible ซึ่งมีไว้ตั้งว่าจะให้แกนมองเห็นได้หรือว่าซ่อนอยู่ ถ้าตั้งเป็น 1 จะมองเห็น ถ้าเป็น 0 จะซ่อน

ดังนั้นผลที่ปรากฏจึงเห็นว่าแกนบนและขวาหายไปโดยสมบูรณ์ เหลือแค่แกนล่างกับซ้ายซึ่งมาตั้งเด่นอยู่ตรงกลาง

นอกจากนี้เส้นแกนยังมีอีกหลายอย่างที่สามารถปรับค่าได้



การตั้งค่าต่างๆของเส้นแกน
นอกจากตำแหน่งแล้วเรายังสามารถตั้งค่าอะไรต่างๆของเส้นแกนได้ด้วยเมธอดต่างๆที่ขึ้นต้นด้วย set_ ได้อีกหลายอย่าง เช่น สี ,ขอบเขต, ความกว้าง, รูปแบบเส้น, ความโปร่งใส

ตัวอย่าง
plt.figure(figsize=(6,6))
ax = plt.axes(facecolor='#FFFFEF')
theta = np.radians(np.linspace(0,360,5000))
for r in np.arange(.5,10):
    x = r*np.cos(theta)
    y = r*np.sin(theta)
    ax.plot(x,y,c='#%dF33%d1'%(9-r,r),lw=5)
ax.spines['right'].set_lw(3) # ความกว้าง
ax.spines['top'].set_lw(15) # ความกว้าง
ax.spines['top'].set_alpha(0.4) # ความโปร่งใส
ax.spines['bottom'].set_color('b') # สี
ax.spines['bottom'].set_bounds(-6,6) # ขอบเขต
ax.spines['left'].set_ls(':') # รูปแบบเส้น
plt.show()




ฟังก์ชัน setp
ในการตั้งค่าอะไรต่างๆของแกนนอกจากปรับด้วยเมธอดต่างๆที่ทำกับแต่ละตัวแกนแล้วยังมีอีกวิธีคือใช้ฟังก์ชัน plt.setp

ฟังก์ชันนี้มีไว้สำหรับปรับแก้ค่าคุณสมบัติต่างๆภายในออบเจ็กต์ ข้อดีสามารถตั้งได้พร้อมกันหลายค่าพร้อมกัน

วิธีการเขียนคือใส่อาร์กิวเมนต์ตัวแรกเป็นออบเจ็กต์ที่ต้องการแก้ค่า ตัวที่สองขึ้นไปคือ คุณสมบัติที่ต้องการปรับแก้=ค่าที่ต้องการ

ตัวอย่างที่แล้วหากเปลี่ยนมาใช้ setp ก็จะเขียนเป็น
plt.setp(ax.spines['right'],linewidth=3)
plt.setp(ax.spines['top'],linewidth=15,alpha=0.4)
plt.setp(ax.spines['bottom'],color='b')
plt.setp(ax.spines['left'],ls=':')

จะเห็นว่าส่วนของ top นั้น linewidth และ alpha ถูกปรับไปพร้อมกันได้ ทำให้การเขียนสั้นลงมาก

และมีแค่ set_bounds เท่านั้นที่ไม่สามารถเขียนแทนด้วย setp ได้ เนื่องจากใช้อาร์กิวเมนต์สองตัว

นอกจากนี้ยังมีวิธีการเขียนอีกแบบคือใส่ชื่อคุณสมบัติแล้วตามด้วยค่าที่ต้องการ จากนั้นหากมีคุณสมบัติอีกตัวที่ต้องการปรับก็ใส่ต่อไปอีกสลับกันไป

ในกรณีนี้ชื่อคุณสมบัติจะต้องเขียนในรูปสายอักขระ มีเครื่องหมายคำพูดคร่อม

หากเขียนด้วยวิธีนี้จะสามารถเขียนใหม่ได้เป็น
plt.setp(ax.spines['right'],'linewidth',3)
plt.setp(ax.spines['top'],'linewidth',15,'alpha',0.4)
plt.setp(ax.spines['bottom'],'color','b')
plt.setp(ax.spines['left'],'ls',':')

ตารางสรุปค่าต่างๆที่สามารถปรับได้
ใช้เมธอด ใช้ setp ความหมาย
set_color color ตั้งค่าสีของเส้น
set_bounds - ตั้งขอบเขตของเส้น หน่วยเป็นไปตามค่าในเส้นกราฟ
set_linewidth
หรือ set_lw
linewidth
หรือ lw
ตั้งความกว้างของเส้น
set_linestyle
หรือ set_ls
linestyle
หรือ ls
ตั้งรูปแบบของเส้น
set_alpha alpha ตั้งค่าความโปร่งใส
set_position position ตั้งค่าตำแหน่ง (รายละเอียดเขียนในหัวข้อที่แล้ว)
set_visible visible ตั้งให้เห็นหรือไม่เห็น: 0 ไม่เห็น 1 เห็น

นอกจากนี้แล้วยังสามารถปรับค่าของออบเจ็กต์หลายอันพร้อมกันได้ด้วย เช่นหากต้องการปรับแกนทั้งหมดทุกอันเหมือนกันก็ใส่ [ax.spines['left'],ax.spines['right'],ax.spines['top'],ax.spines['bottom']] เป็นอาร์กิวเมนต์ตัวแรกได้เลย หรืออาจเขียนย่อเป็น [ax.spines[x] for x in ax.spines] หรือ list(ax.spines.values()) ก็ได้

ตัวอย่าง
theta = np.radians(np.linspace(0,360,5000))
r = 1+np.cos(theta*55)+np.sin(theta*60)
x = r*np.cos(theta)
y = r*np.sin(theta)
plt.figure(figsize=(6,6))
ax = plt.axes(facecolor='#DDFFFF')
ax.plot(x,y,c='#11FF11')
plt.setp([ax.spines[x] for x in ax.spines],color='#FF8800',lw=3,ls='--')
plt.show()


setp ยังใช้กับอย่างอื่นได้อีกหลายอย่าง เช่นกับ xaxis และ yaxis

ตัวอย่าง
x = np.linspace(-5,5,2000)
y = np.sin(x*20)+x**3/50
ax = plt.axes(facecolor='#FEEEFE')
ax.set_xlabel('x',fontsize=14)
ax.set_ylabel(r'$\sin(20x)+\frac{x^3}{50}$',fontsize=16,rotation=-90,labelpad=45)
ax.tick_params(labelsize=14,direction='inout',length=12)
plt.setp(ax.xaxis,label_position='top',ticks_position='bottom')
plt.setp(ax.yaxis,label_position='right',ticks_position='left')
ax.plot(x,y,c='#AA77EE')
plt.show()





อ้างอิง


<< บทที่แล้ว     บทถัดไป >>
หน้าสารบัญ


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> matplotlib

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

目录

从日本来的名言
模块
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
机器学习
-- 神经网络
javascript
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  查看日志

  推荐日志

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ