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



numpy & matplotlib เบื้องต้น บทที่ ๑๑: การประกอบกราฟเข้าด้วยกัน
เขียนเมื่อ 2016/06/11 18:52
แก้ไขล่าสุด 2021/09/28 16:42
ในบทที่แล้วได้พูดถึงการนำกราฟหลายอันมารวมอยู่ในภาพเดียวกันแล้ว แต่ว่ากราฟแต่ละอันก็แยกกันอยู่คนละส่วน เหมือนแค่เอามาวางคู่กันเฉยๆ

ดังนั้นในบทนี้จะพูดถึงการนำเอากราฟมาประกอบกัน



การใช้ twinx และ twiny เพื่อนำแกนมาซ้อนกัน
ในบางครั้งเราเขียนกราฟของคนละสิ่งกันซึ่งมีมาตราส่วนและขอบเขตที่ต่างกันออกไปแต่ว่าต้องการเอามาเทียบกัน จึงต้องนำมาซ้อนทับกัน

ปกติ ถ้ามีการนำกราฟมาซ้อนกันด้วย subplot กราฟที่ถูกเขียนก่อนจะถูกทับหายไปทันที ไม่ได้ถูกเขียนซ้อนกัน ทำให้ต้องใช้วิธีการบางอย่างหากต้องการนำกราฟมาซ้อนกัน

การจะสามารถเขียนกราฟ ๒ กราฟให้ซ้อนอยู่บนที่เดียวกันได้อาจมีหลายวิธี ในที่นี้จะแนะนำวิธีการด้วยการใช้เมธอด twinx และ twiny

twinx และ twiny เป็นเมธอดของ axes ซึ่งมีไว้สร้าง axes อันใหม่ขึ้นอีกอันที่มีการใช้แกน x หรือ y ร่วมกัน

twinx คือเพิ่ม axes ใหม่ที่มีแกน x ร่วมกัน แต่ y ต่าง
twiny คือเพิ่ม axes ใหม่ที่มีแกน y ร่วมกัน แต่ x ต่าง

ขอยกตัวอย่างด้วยกราฟที่เทียบประชากรกับ GDP ของญี่ปุ่นตั้งแต่ปี 1950
(ข้อมูลจาก https://ja.wikipedia.org/wiki/国内総生産 และ https://ja.wikipedia.org/wiki/日本の人口統計)

ถ้าใช้ subplot ก็จะออกมาแบบนี้
import matplotlib.pyplot as plt
pi = range(1950,2011,10)
pop = [84115,94302,104665,117060,123611,126962,128058]
gdp = [71683.1,188323.1,290551.1,284375.0,447369.9,474847.2,512364.6]
ax1 = plt.subplot(2,1,1)
ax1.set_title(u'ประชากร',fontname='Tahoma',fontsize=15)
ax1.plot(pi,pop)
ax2 = plt.subplot(2,1,2)
ax2.set_title('GDP',y=0.8)
ax2.plot(pi,gdp)
plt.show()



จากนั้นลองเปลี่ยนมาวางกราฟซ้อนกันดู ในที่นี้เราต้องการกราฟที่มี x เหมือนกัน คือเป็นปีเหมือนกัน แต่ที่ต่างคือแกน y ดังนั้นใช้ twinx

จะเขียนเป็น
pi = range(1950,2011,10)
pop = [84115,94302,104665,117060,123611,126962,128058]
gdp = [71683.1,188323.1,290551.1,284375.0,447369.9,474847.2,512364.6]
ax1 = plt.gca()
ax1.set_title(u'ประชากร',fontname='Tahoma',fontsize=15)
ax1.plot(pi,pop)
ax2 = ax1.twinx()
ax2.set_title('GDP')
ax2.plot(pi,gdp)
plt.show()



ผลที่ได้จะเห็นว่าแกน x ถูกใช้ร่วมกัน และแกน y ของกราฟที่เพิ่มเข้ามาก็ไปอยู่ทางขวาแทน

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

พอแก้แล้วก็จะเป็นแบบนี้
import matplotlib.pyplot as plt
import matplotlib as mpl
fp = mpl.font_manager.FontProperties(family='Tahoma',size=16)
pi = range(1950,2011,10)
pop = [84115,94302,104665,117060,123611,126962,128058]
gdp = [71683.1,188323.1,290551.1,284375.0,447369.9,474847.2,512364.6]
ax1 = plt.gca()
ax1.set_xlabel(xlabel=u'ปี',fontproperties=fp)
ax1.plot(pi,pop,'m',label=u'ประชากร')
ax1.legend(loc=2,prop=fp,fontsize=15)
ax2 = ax1.twinx()
ax2.plot(pi,gdp,'r',label='GDP')
ax2.legend(loc=4)
plt.show()





การใช้ subplot เพื่อเชื่อมโยงกราฟเข้าด้วยกัน
บางครั้งเราก็อาจไม่ได้ต้องการให้กราฟซ้อนกัน แต่ต้องการจับมาเรียงต่อกันเพื่อแสดงความสัมพันธ์อะไรบางอย่าง

แต่การแค่จัดกราฟมาเรียงต่อกันเฉยๆด้วย subplot อาจจะยังดูไม่สวย ดังนั้นอาจต้องมีการจัดการอะไรเพิ่มเติม

ตัวอย่าง ลองดูกราฟที่เปรียบเทียบการสั่นของวัตถุที่ถูกหน่วง เมื่อนำมา subplot ต่อกันโดยไม่ได้ตกแต่งอะไรเป็นพิเศษก็จะได้เป็นแบบนี้
import numpy as np
x = np.linspace(0,16,500)
plt.subplot(311)
plt.plot(x,np.cos(x),'m')
plt.subplot(312)
plt.plot(x,np.cos(0.995*x)*np.exp(-0.1*x),'m')
plt.subplot(313)
plt.plot(x,np.cosh(0.458*x)*np.exp(-1.1*x),'m')
plt.show()



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

เมื่อพิจารณาดูแล้วสิ่งที่ควรต้องทำก็คือ
- ตั้งขอบเขตของแกน y ให้เท่ากันหมด ใช้ ylim
- ใส่ตัวหนังสืออธิบายความหมายของ y ในกราฟแต่ละกราฟ ใช้ ylabel
- เลื่อน ylabel มาอยู่ตรงกลาง หมุนให้เป็นแนวนอน แล้วขยายให้เห็นชัด ใช้ yaxis.set_label_coords, fontsize=20 และ rotation=0
- ใส่ชื่อแกน x เฉพาะกราฟล่างสุด
- ลบตัวเลขในแกน x ของ ๒ กราฟบนออก ใช้ tick_params(labelbottom='off')

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

พอลองแก้ดูแล้วก็จะออกมาเป็นแบบนี้
x = np.linspace(0,16,500)
ax1 = plt.subplot(311,ylim=(-1,1))
ax1.set_ylabel('$cos(t)$',fontsize=14,rotation=0)
ax1.tick_params(labelbottom='off')
ax1.yaxis.set_label_coords(0.5, 0.7)
ax1.plot(x,np.cos(x),'m')
ax2 = plt.subplot(312,ylim=(-1,1))
ax2.set_ylabel('$e^{-0.1t}cos(0.995t)$',fontsize=14,rotation=0)
ax2.tick_params(labelbottom='off')
ax2.yaxis.set_label_coords(0.5, 0.7)
ax2.plot(x,np.cos(0.995*x)*np.exp(-0.1*x),'m')
ax3 = plt.subplot(313,ylim=(-1,1),xlabel='t')
ax3.set_ylabel('$e^{-1.1t}cosh(0.458t)$',fontsize=14,rotation=0)
ax3.yaxis.set_label_coords(0.5, 0.7)
ax3.plot(x,np.cosh(0.458*x)*np.exp(-1.1*x),'m')
plt.show()





การสร้างกราฟซ้อนกราฟ
บางครั้งแทนที่จะเอากราฟมาวางต่อกัน หากเอากราฟมาวางซ้อนกันอาจสะดวกกว่า

หาก ใช้ plt.axes แล้วเราสามารถจะวางกราฟซ้อนกันยังไงก็ได้ ในที่นี้เราจะลองสร้างกราฟใหญ่ขึ้นมาอันหนึ่งแล้วสร้างกราฟอันเล็กที่ขยาย ส่วนหนึ่งบนนั้น

ตัวอย่าง
x = np.linspace(0,10,10001)
y = np.sin(x)+np.sin(x*100)/10
plt.axes([0.08,0.05,0.87,0.9],ylim=[-1.2,1.3]) # กราฟหลัก
plt.plot(x,y)
plt.plot([1.3,1.8,1.8,1.3,1.3],[1.2,1.2,0.8,0.8,1.2],'r') # วาดกรอบสีแดงเพื่อระบุจุดที่จะขยาย

ax = plt.axes([0.5,0.5,0.42,0.42],xlim=[1.3,1.8],ylim=[0.8,1.2]) # กราฟเล็ก กำหนด xlim และ ylim ให้ต่างจากกราฟหลัก
plt.setp(list(ax.spines.values()),color='r')
plt.plot(x,y) # พล็อตโดยใช้ x,y ตัวเดียวกัน แต่ขอบเขตต่างกัน
plt.show()





อ้างอิง


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


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

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

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

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> 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月

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

ไทย

日本語

中文