φυβλαςのβλογ
บล็อกของ phyblas



numpy & matplotlib เบื้องต้น บทที่ ๗: การปรับแต่งส่วนประกอบของกราฟ
เขียนเมื่อ 2016/06/11 13:36
แก้ไขล่าสุด 2022/07/21 20:02
หลังจากที่บทที่แล้วได้เรียนรู้ส่วนประกอบของฉากที่ใช้กราฟไปแล้ว คราวนี้จะมาลองดูวิธีการปรับแต่งต่างๆ



การปรับขนาดของภาพ
ในตัวอย่างในบทที่ผ่านๆมาเราวาดกราฟโดยที่ไม่ได้กำหนดขนาด ซึ่งจะเห็นว่ากราฟที่ได้ออกมามีขนาดเป็นค่ามาตรฐานค่าหนึ่ง

เช่นลอง
import numpy as np
import matplotlib.pyplot as plt
theta = np.radians(np.linspace(0,360,73))
x = 10*np.cos(theta)
y = 10*np.sin(theta)
plt.plot(x,y)
plt.show()



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

เราสามารถปรับขนาดของภาพได้ด้วยการเติมคีย์เวิร์ดในฟังก์ชัน plt.figure

คีย์เวิร์ดที่เกี่ยวข้องมีอยู่ ๒ ตัวคือ figsize และ dpi

figsize คือขนาดของรูปในแนวตั้งและแนวนอน โดยต้องใส่ในรูปทูเพิลหรือลิสต์ มีหน่วยเป็นนิ้ว 1 นิ้วคือ 80 พิกเซลเป็นมาตรฐาน

ค่า figsize มาตรฐานจะเป็น  8x6 ดังนั้นจึงได้ภาพขนาด 640x480 อย่างไรก็ตามอาจมีความต่างไปตามคอมไพเลอร์ที่ใช้

จำนวนพิกเซลต่อนิ้วก็สามารถปรับได้ด้วยการใส่คีย์เวิร์ด dpi ยิ่งค่ามากภาพก็จะยิ่งใหญ่ ขนาดของภาพที่ได้ก็คือ figsize คูณด้วย dpi

ลองแก้ส่วนวาดกราฟเป็น
plt.figure(figsize=[5,5],dpi=40)
plt.plot(x,y)
plt.show()

แบบนี้จะได้ภาพขนาด 200x200 พิกเซล



ตอนที่เซฟภาพด้วยฟังก์ชัน savefig จะต้องปรับค่า dpi อีกทีด้วยการใส่คีย์เวิร์ด ค่า dpi ที่ปรับที่ figsize จะไม่มีผล ดังนั้นหากต้องการเซฟภาพขนาดเท่าเดิมก็พิมพ์
plt.savefig('wongklom.png',dpi=40)



การแต่งสีและขอบของภาพ
นอกจากปรับขนาดแล้วก็ยังสามารถปรับสีและขอบของภาพได้ด้วย คีย์เวิร์ดที่เกี่ยวข้องมีดังนี้
facecolor สีพื้นหลัง
edgecolor สีขอบ
linewidth ความกว้างขอบ
figsize ขนาดภาพในหน่วยนิ้ว [แนวตั้ง,แนวนอน]
dpi สัดส่วนพิกเซลต่อนิ้ว

ลอง

theta = np.radians(np.linspace(0,360,73))
x = 10*np.cos(theta)
y = 10*np.sin(theta)
plt.figure(figsize=[5,5],dpi=60,edgecolor='#AA1111',linewidth=15,facecolor='#99DDFF')
plt.plot(x,y)
plt.show()

ได้กราฟออกมาแลดูสวยงาม



คีย์เวิร์ดต่างๆที่ปรับลงไปเหล่านี้เวลาที่เซฟภาพก็ต้องใส่ลงในฟังก์ชัน savefig เช่นกัน ไม่เช่นนั้นภาพที่ได้ก็จะยังคงเป็นสีขาวโล่ง



การปรับขอบเขตของกราฟ
ปกติถ้าเราไม่ได้ตั้งว่าขอบเขตของกราฟเป็นเท่าใดโปรแกรมจะทำการหาตามความเหมาะสมให้เอง แต่บางครั้งก็อาจไม่ได้ถูกใจเสมอไป ดังนั้นจึงอาจต้องกำหนดเขตใหม่เพื่อให้ได้ตามแบบที่ต้องการ

การปรับขอบเขตสามารถทำได้ด้วยฟังก์ชัน plt.axes

คีย์เวิร์ดที่ต้องใส่คือ xlim และ ylim โดยค่าที่ต้องใส่คือทูเพิลหรือลิสต์ขอบเขต xlim=[ซ้าย, ขวา], ylim=[ล่าง, บน]

ตัวอย่าง
theta = np.radians(np.linspace(0,10000,2001))
x = 10*np.cos(theta)/(100+theta)
y = 10*np.sin(theta)/(100+theta)
plt.figure(edgecolor='#AA1111',linewidth=10,facecolor='#AAFFEE')
plt.axes(xlim=[-0.16,0.16],ylim=[-0.12,0.12])
plt.plot(x,y,c='#EE2211')
plt.show()





การปรับตำแหน่งและตัวเลขขีดพิกัด
นอกจากจะปรับขอบเขตแล้วเรายังสามารถปรับเส้นขีดที่บอกตำแหน่งได้ด้วย จากที่ปกติจะถูกกำหนดโดยอัตโนมัติตามความเหมาะสม สามารถทำได้โดยเพิ่มคีย์เวิร์ด xticks และ yticks ค่าที่ต้องใส่คือลิสต์หรืออาเรย์ไล่เรียงตำแหน่งขีด

np.linspace น่าจะเป็นฟังก์ชันที่เหมาะในการสร้างอาเรย์เพื่อใช้ในการนี้ เพราะสามารถกำหนดขอบเขตและขีดให้เว้นระยะเท่าๆตามจำนวนที่ต้องการได้

ลองดูกราฟเดิม
theta = np.radians(np.linspace(0,10000,2001))
x = 10*np.cos(theta)/(100+theta)
y = 10*np.sin(theta)/(100+theta)
plt.figure(edgecolor='#1111AA',linewidth=10,facecolor='#AAFFEE')
plt.axes(xlim=[-0.16,0.16],ylim=[-0.12,0.12],
         xticks=np.linspace(-0.16,0.16,9),
         yticks=np.linspace(-0.11,0.11,12))
plt.plot(x,y,c='#EE2211')
plt.show()



จะเห็นว่าจำนวนขีดเพิ่มขึ้นตามที่ต้องการ

นอกจากนี้ยังสามารถแก้ไขตัวหนังสือที่ขีดบอก โดยเพิ่มคีย์เวิร์ด yticklabels และ xticklabels โดยใส่ค่าเป็นรายการของสายอักขระ

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

แก้กราฟเป็นตามนี้ โดยเพิ่ม yticklabels และ xticklabels เข้าไป
plt.figure(edgecolor='#11AA11',linewidth=10,facecolor='#FFAAEE')
xlim = [-0.16,0.16]
ylim = [-0.12,0.12]
xticks = np.linspace(-0.16,0.16,9)
yticks = np.linspace(-0.11,0.11,12)
xticklabels = ['%.2fcm'%s for s in xticks]
yticklabels = ['%.2fcm'%s for s in yticks]
plt.axes(xlim=xlim,ylim=ylim,xticks=xticks,yticks=yticks,yticklabels=yticklabels,xticklabels=xticklabels)
plt.plot(x,y,c='#EE2211')
plt.show()

จะได้ว่ามีคำว่า cm เพิ่มเข้ามาในกราฟ



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

นอกจากนี้แล้วการตั้งค่าต่างๆนี้อาจทำได้โดยใช้เมธอดที่ออบเจ็กต์ axes ซึ่งอาจใช้ฟังก์ชัน gca เพื่อนำเอาออบเจ็กต์ตัว axes นั้นมาจัดการ

เมธอดเหล่านี้ล้วนขึ้นต้นด้วยคำว่า set_ เช่น set_xlim, set_ylim, set_xticks, set_yticks เป็นต้น

ตัวอย่างข้างต้นอาจเขียนใหม่ด้วยวิธีนี้ได้เป็น
plt.figure(edgecolor='#11AA11',linewidth=10,facecolor='#FFAAEE')
ax = plt.gca()
ax.set_xlim([-0.16,0.16])
ax.set_ylim([-0.12,0.12])
ax.set_xticks(np.linspace(-0.16,0.16,9))
ax.set_yticks(np.linspace(-0.11,0.11,12))
ax.set_xticklabels(['%.2fcm'%s for s in np.linspace(-0.16,0.16,9)])
ax.set_yticklabels(['%.2fcm'%s for s in np.linspace(-0.11,0.11,12)])
plt.plot(x,y,c='#EE2211')
plt.show()

ผลที่ได้จะเหมือนกับตัวอย่างที่แล้วแต่จะเขียนยาวกว่าหน่อยเพราะต้องมีการเอาตัวแปร ax มารับด้วยเพื่อจะนำมาเรียกใช้เพื่อการปรับค่าในบรรทัดต่อๆมา

หรือนอกจากนี้แล้วก็อาจเขียนสั้นง่ายกว่านั้นโดยโดยใช้ฟังก์ชัน plt.xlim, plt.ylim, plt.xticks และ plt.yticks โดยไม่จำเป็นต้องไปดึงเอาออบเจ็กต์ตัว axes มาเลยก็ได้ เช่น
plt.figure(edgecolor='#11AA11',linewidth=10,facecolor='#FFAAEE')
plt.xlim([-0.16,0.16])
plt.ylim([-0.12,0.12])
plt.xticks(np.linspace(-0.16,0.16,9),['%.2fcm'%s for s in np.linspace(-0.16,0.16,9)])
plt.yticks(np.linspace(-0.11,0.11,12),['%.2fcm'%s for s in np.linspace(-0.11,0.11,12)])
plt.plot(x,y,c='#EE2211')
plt.show()

เพียงแต่มีข้อแตกต่างคือจะสังเกตได้ว่าในที่นี้ plt.xticks จะใช้แทนทั้ง set_xticks และ set_xticklabels ไปในเวลาเดียวกันเลย แต่ไม่มีฟังก์ชัน plt.xticklabels ดังนั้นต้องระวังอย่าสับสนตรงนี้ด้วย

นอกจากนั้นแล้ว ในทางตรงข้ามกับ set_ เรายังสามารถดูค่าต่างๆของ axes นั้นได้ด้วยเมธอดที่ขึ้นต้นด้วย get_
print(ax.get_xlim()) # ได้ (-0.16, 0.16)
print(ax.get_xticks()) # ได้ [-0.16 -0.12 -0.08 -0.04 0. 0.04 0.08 0.12 0.16]

นอกจากนี้ยังมีวิธีอื่นการปรับตำแหน่งและรูปแบบการแสดงผลของเลขขีดบนกราฟซึ่งอาจจะเข้าใจยากกว่าแต่ค่อนข้างสะดวกกว่า ซึ่งจะพูดถึงในบทที่ ๓๗



การควบคุมสัดส่วนของ x และ y ในกราฟ
จะเห็นว่าพอปรับ xlim และ ylim ก็จะทำให้สัดส่วนของค่า x และ y เปลี่ยนไปด้วย การปรับ xlim และ ylim ก็เป็นการช่วยปรับสัดส่วนของ x และ y ไปด้วย แต่ว่าแบบนั้นควบคุมสัดส่วนได้ยาก ไหนจะต้องคำนึงถึงขนาดของ figure ด้วย

กรณีที่ต้องการกำหนดสัดส่วนของค่า x และ y ให้แน่นอนอาจใส่คีย์เวิร์ด aspect เพิ่มลงไปในฟังก์ช้น plt.axes

ค่า aspect คือสัดส่วนระหว่างด้านแกน y ต่อแกน x ถ้าใส่เป็น 1 สัดส่วนจะเท่ากัน ถ้าใส่ 0.5 x จะยืดใหญ่กว่า y สองเท่า เป็นต้น

นอกจากใส่เป็นตัวเลขแล้วอาจใส่เป็นสายอักขระ ซึ่งคำที่ใส่ได้คือ equal หมายถึง xy เท่ากัน (=1) และ auto หมายถึงปรับอัตโนมัติ

ตัวอย่าง
theta = np.radians(np.linspace(0,2000,5001))
r = 10*(10+(theta+np.cos(theta**3/100)**2))/(30+theta)
x = r*np.cos(theta)
y = r*np.sin(theta)
plt.figure(facecolor='#228899')
plt.axes(aspect=0.5)
plt.plot(x,y,c='#9933AA')
plt.show()



นอกจากนี้ยังอาจปรับได้ทีหลังด้วยเมธอด set_aspect

เช่นลองพิมพ์ลงไปตามนี้แล้วกลับไปดูที่ภาพอีกทีก็จะพบว่ากลายเป็นสัดส่วนเท่ากัน
ax = plt.gca()
ax.set_aspect('equal')




การปรับขอบเขต axes ภายใน figure
ในตัวอย่างที่ผ่านมาเราจะเห็นว่าขนาดของกราฟจะถูกกำหนดตายตัว ซึ่งบางทีอาจรู้สึกว่าเหลือพื้นที่ขอบมากเกินไปใช้ไม่คุ้ม

หากต้องการปรับ axes ได้อย่างอิสระให้ใส่อาร์กิวเมนต์ตัวแรกลงไปภายใน plt.axes ก่อนที่จะใส่คีย์เวิร์ดต่างๆเช่นพวก xlim ylim อย่างที่ผ่านมา

โดยอาร์กิวเมนต์ที่ต้องใส่นั้นคือลิสต์ที่ประกอบไปด้วยค่า [ขอบซ้าย,ขอบล่าง,ความกว้าง,ความสูง] โดยทั้งหมดมีหน่วยเป็นสัดส่วนต่อความกว้างและความยาวของภาพทั้งภาพ (ถ้า 1 คือเต็มภาพ)

ตัวอย่าง
theta = np.radians(np.linspace(0,3000,2001))
r = (10+(theta+np.cos(theta**2/10)**2))/(100+theta)
x = r*np.cos(theta)
y = r*np.sin(theta)
plt.figure(figsize=[5,5],facecolor='#66AAEE')
plt.axes([0,0,1,1],xlim=[-0.42,0.42],ylim=[-0.42,0.42])
plt.plot(x,y,c='#99EE11')
plt.show()



แบบนี้จะได้ภาพเต็มจอทั้งหมดเป็นกราฟที่เราวาด ทำให้ไม่เห็นเส้นแกนและขีดกับตัวเลขบอกค่า

ลองปรับลดลงมาหน่อยให้พอเห็น
plt.axes([0.05,0.05,0.93,0.93],xlim=[-0.42,0.42],ylim=[-0.42,0.42])

แบบนี้ก็จะเล็กลงมาจนตัวเลขอยู่ในกรอบ



การเปลี่ยนสีฉากหลัง
อีกอย่างที่สามารถเปลี่นได้ก็คือสีฉากหลังของกราฟ ทำได้โดยใส่คีย์เวิร์ด facecolor เพิ่มเข้าไป

ตัวอย่าง
theta = np.radians(np.linspace(0,20000,10001))
x = (10+np.cos(theta*10)/0.5)*np.cos(theta)/(50+theta**1.2)
y = (10+np.cos(theta*10)/0.5)*np.sin(theta)/(50+theta**1.2)
plt.axes(facecolor='#222222',xlim=[-0.16,0.16],ylim=[-0.12,0.12])
plt.plot(x,y,c='#EEEEEE',marker='o',alpha=0.5,ls='-.')
plt.show()



หรืออาจตั้งค่าที่ตัวออบเจ็กต์ axes โดยใช้คำสั่ง set_facecolor ก็ได้เช่นกัน

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

สรุปคีย์เวิร์ดที่ใส่ใน axes เพื่อปรับตั้งค่าต่างๆได้ (เฉพาะที่กล่าวถึงไปแล้วในบทนี้)
คีย์เวิร์ด ฟังก์ชัน เมธอด ความหมาย
xlim plt.xlim set_xlim ขอบเขตในแกน x
ylim plt.ylim set_ylim ขอบเขตในแกน y
xticks plt.xticks set_xticks ค่าตำแหน่งขีดบอกในแกน x
xticklabels set_xticklabels ข้อความที่ขีดบอกในแกน x
yticks plt.yticks set_yticks ค่าตำแหน่งขีดบอกในแกน y
yticklabels set_yticklabels ข้อความที่ขีดบอกในแกน y
aspect - set_aspect สัดส่วนค่าแกน y ต่อ x
facecolor - set_facecolor สีฉากหลัง



สรุปเนื้อหา
จบบทนี้เราก็สามารถปรับแต่งอะไรได้หลากหลายมากมายแล้ว แต่ก็ยังไม่หมดแค่นั้น ยังมีลูกเล่นอีกมากมายที่สามารถทำได้ใน matplotlib

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

เช่นเราอาจใส่คีย์เวิร์ด xticks, xticklabels, ฯลฯ ลงไปในวงเล็บ () หลัง plt.axes พร้อมกันทีเดียวหรือจะใช้ plt.gca() เอาตัวออบเจ็กต์ axes มาปรับค่าด้วยเมธอด set_ ต่างๆที่ตัวออบเจ็กต์นั้นภายหลังก็ได้ หรืออาจใช้ฟังก์ชันเช่น plt.xlim หรือ plt.xticks ก็ได้

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



อ้างอิง


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


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

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

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

หมวดหมู่

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

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

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



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

  ค้นหาบทความ

  บทความแนะนำ

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

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文