φυβλαςのβλογ
บล็อกของ 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)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

ไทย

日本語

中文