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



numpy & matplotlib เบื้องต้น บทที่ ๑๒: แผนภูมิแท่ง
เขียนเมื่อ 2016/06/11 21:46
แก้ไขล่าสุด 2022/07/21 20:28
ในบทที่ผ่านๆมาเราพูดถึงแต่เรื่องของกราฟเส้นธรรมดามาโดยตลอด แต่ความจริงแล้ว matplotlib สามารถวาดกราฟชนิดต่างๆได้มากมาย

บทนี้จะพูดถึงกราฟอีกชนิดที่ใช้กันบ่อย นั่นคือแผนภูมิแท่ง



การวาดแผนภูมิแท่ง
แผนภูมิแท่งสามารถสร้างได้โดยใช้ฟังก์ชัน bar โดยพื้นฐานแล้วค่าที่ต้องป้อนเข้าไปก็คล้ายกับ plot ที่ใช้วาดกราฟเส้น นั่นคือใส่อาร์กิวเมนต์สองตัวเป็นค่าในแกน x กับ y เพียงแต่ว่าค่าในแกน y ในที่นี้จะกลายเป็นความสูงของแท่ง

ตัวอย่าง
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0,30)
y = np.sqrt(x)
plt.bar(x,y)
plt.show()



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

ส่วนสีของเส้นขอบสามารถปรับได้โดยคีย์เวิร์ด edgecolor หรือย่อว่า ec ความหนาของเส้นขอบปรับได้ด้วยคีย์เวิร์ด linewidth หรือย่อว่า lw รูปแบบของเส้นขอบปรับได้ด้วยคีย์เวิร์ด linestyle หรือย่อว่า ls

ลองใช้ข้อมูลเดิมมาวาดแผนภูมิแท่งดูใหม่โดยเปลี่ยนสีและความกว้างของเส้นขอบแท่ง คราวนี้ใส่กราฟเส้นไปด้วยเป็นตัวเปรียบเทียบ
plt.bar(x,y,color='r',ec='b',lw='2')
plt.plot(x,y,c='r')
plt.show()



เมื่อเทียบกับกราฟเส้นแล้วจะเห็นว่าตำแหน่งในกราฟเส้นเทียบเท่ากับมุมซ้ายของแท่ง แบบนี้เท่ากับว่าแท่งมีความโน้มเอียงไปทางขวา

แต่สามารถจะแก้ให้การจัดเรียงอยู่ตรงกลางได้โดยเพิ่มคีย์เวิร์ด align='center'
plt.bar(x,y,color='r',align='center')
plt.plot(x,y,c='r')
plt.xlim([0,30])
plt.show()



ความกว้างของแท่งสามารถปรับได้ที่คีย์เวิร์ด width
plt.bar(x,y,color='m',align='center',width=0.4)
plt.xlim([0,30])
plt.show()



ถ้าหากตั้งแกน x เป็นลอการิธึมจะเห็นว่าความกว้างของแกนดูเหมือนลดลงเรื่อยๆ (แต่จริงๆเท่าเดิม)
plt.figure(figsize=[9,5])
ax = plt.axes(xscale='log')
plt.bar(x,y,color='c',align='center',width=0.4)
ax.set_xlim([x[1],x.max()])
plt.show()





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

การปรับสีทำได้โดยใช้ฟังก์ชัน set_facecolor เช่น
x = np.linspace(0,3,30)
y = np.sqrt(x)
bara = plt.bar(x,y,align='center',width=0.1,ec='k')
bara[27].set_facecolor('g')
plt.show()

จะได้แท่งที่มีสีประหลาดอยู่แท่งเดียว




หรืออาจเขียนไอ้อีกแบบ คือใช้ setp ก็ได้
plt.setp(bara[27],facecolor='g')

หรือจะใช้ for เพื่อทำแท่งที่ไล่สีต่างกันออกไปหมดก็ทำได้
x = np.linspace(1,4,30)
bara = plt.bar(x,1/x**2,width=0.1)
for i in range(30):
    bara[i].set_facecolor((0.03*i,1-0.03*i,0.1))
    # หรือ plt.setp(bara[i],facecolor=(0.03*i,1-0.03*i,0.1))
plt.xlim(x.min(),x.max())
plt.show()



เราสามารถทำให้สีเปลี่ยนไปตามความสูงได้ การหาค่าความสูงของแท่งทำได้โดยใช้เมธอด get_height
x = np.linspace(-1,1,40)
bara = plt.bar(x,1-x**2,width=0.05)
for i in range(40):
    h = bara[i].get_height()
    bara[i].set_facecolor((h,1-h,0.5*h))
plt.show()





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

เช่นเราต้องการวาดแผนภูมิแท่งแสดงจำนวนประชากรของจังหวัด ๕ จังหวัดที่มีประชากรสูงสุดในไทยปี 2015
(ข้อมูลจาก https://th.wikipedia.org/wiki/รายชื่อจังหวัดในประเทศไทยเรียงตามจำนวนประชากร)

สามารถเปลี่ยนตัวเลขเป็นตัวหนังสือตามที่ต้องการได้โดยใช้ set_xticklabels แล้วใส่ลิสต์ของข้อความที่ต้องการลงไป
x = np.arange(1,6)
y = [5696409,2628818,1857429,1798014,1728242]
mueang = ['Bangkok','Nakhonratchasima','Ubonratchathani','Khonkaen','Chiangmai']
ax = plt.axes(xticks=x) # กำหนดให้ขีดวางตรงทุกค่าตำแน่งที่ป้อนเข้าไป (คือ 1 ถึง 5)
ax.set_xticklabels(mueang,rotation=10) # ใส่ชื่อจังหวัดลงไปแทนตัวเลข 1 ถึง 5
plt.bar(x,y)
plt.show()



ในที่นี้มีการทำให้อักษรเอียงด้วยโดยเพิ่มคีย์เวิร์ด rotation ไม่เช่นนั้นจะซ้อนทับกัน

ต่อมาลองเปลี่ยนตัวหนังสือให้เป็นภาษาไทยดู ซึ่งยุ่งยากขึ้นเล็กน้อยตรงที่ต้องเปลี่ยนฟอนต์ วิธีการกำหนดฟอนต์ได้เขียนไว้ในบทที่ ๘ แล้ว ทำในลักษณะเดียวกันเราก็สามารถปรับฟอนต์โดยใส่คีย์เวิร์ด fontproperties ลงใน set_xticklabels ได้
import matplotlib as mpl
fp = mpl.font_manager.FontProperties(family='Tahoma',size=15)
x = np.arange(1,6)
y = [5696409,2628818,1857429,1798014,1728242]
mueang = [u'กรุงเทพฯ',u'นครราชสีมา',u'อุบลราชธานี',u'ขอนแก่น',u'เชียงใหม่'] # ไพธอน 3 ไม่ต้องมี u ก็ได้
ax = plt.axes(xticks=x)
ax.set_xticklabels(mueang,rotation=10,fontproperties=fp)
plt.bar(x,y,color='g')
plt.show()



จะเห็นว่าข้อความมาแทนตัวเลขบอกตำแหน่ง 1,2,3,4,5 แม้เราจะไม่ได้ใช้ตัวเลขแต่ก็จำเป็นต้องกำหนดตัวเลขก่อนเพื่อเป็นการระบุว่า จะตั้งแท่งไว้ตรงไหน



การรวมแท่งของข้อมูลหลายชุดเข้าด้วยกัน
บางครั้งเราอาจต้องการเขียนแผนภูมิแท่งของข้อมูลหลายชุดวางไว้ด้วยกัน เราสามารถใช้คำสั่ง bar ซ้อนกันหลายครั้งได้เช่นเดียวกันกับ plot

เช่นลองวาดแผนภูมิแท่งแสดงข้อมูลประชากรญี่ปุ่นในแต่ละปีโดยแบ่งเป็นช่วงอายุต่างๆแบ่งเป็น ๓ ช่วง ดังนั้นมีข้อมูล ๓ ชุดที่จะใส่ไว้ด้วยกัน
x = [1950,1970,1990,2010]
y1 = [29776710,25167960,22497202,16903660]
y2 = [50132540,72253019,85909645,81572946]
y3 = [4121635,7445521,14833320,29581398]
plt.axes(xticks=x)
plt.bar(x,y1,color='b',width=9,label='0-14',align='center')
plt.bar(x,y2,color='y',width=9,label='15-64',align='center')
plt.bar(x,y3,color='r',width=9,label='65+',align='center')
plt.legend(loc=2)
plt.show()



แต่จะเห็นว่าผลที่ได้คือแท่งซ้อนทับกัน เนื่องจากถูกวางในตำแหน่งเดียวกัน

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

เปลี่ยนจากลิสต์เป็นอาเรย์เพื่อที่จะบวกได้ง่าย จากนั้นตอนวาดก็เลื่อนแท่งแรกไปเป็น x-3 แท่งสุดท้ายเป็น x+3 กำหนดความกว้างแท่งเป็น 3 เท่านี้ก็จะได้ ๓ แท่งที่วางติดกัน
x = np.array([1950,1970,1990,2010])
y1 = np.array([29776710,25167960,22497202,16903660])
y2 = np.array([50132540,72253019,85909645,81572946])
y3 = np.array([4121635,7445521,14833320,29581398])
plt.axes(xticks=x)
plt.bar(x-3,y1,color='b',width=3,label='0-14',align='center')
plt.bar(x,y2,color='y',width=3,label='15-64',align='center')
plt.bar(x+3,y3,color='r',width=3,label='65+',align='center')
plt.legend(loc=2)
plt.show()





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

bar มีคีย์เวิร์ดที่กำหนดความสูงของฐานของแท่ง นั่นคือ bottom หากเรากำหนดให้ค่า bottom เป็นเท่ากับค่าของตัวที่วางก่อนหน้าก็จะได้แท่งที่วางต่อกัน

เขียนใหม่ได้แบบนี้
x = np.array([1950,1970,1990,2010])
y1 = np.array([29776710,25167960,22497202,16903660])
y2 = np.array([50132540,72253019,85909645,81572946])
y3 = np.array([4121635,7445521,14833320,29581398])
plt.axes(xticks=x)
plt.bar(x,y1,color='b',width=9,label='0-14',align='center')
plt.bar(x,y2,color='y',bottom=y1,width=9,label='15-64',align='center')
plt.bar(x,y3,color='r',bottom=y1+y2,width=9,label='65+',align='center')
plt.legend(loc=2)
plt.show()





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

การทำให้แท่งหันลงก็ทำได้ง่ายด้วยการใส่ค่าติดลบให้กับแท่งที่ต้องการให้ชี้ลง
x = np.linspace(0,1.2,60)
plt.bar(x,np.sin(x*10)**2,color='m',width=0.02)
plt.bar(x,-np.cos(x*10)**2,color='r',width=0.02)
plt.show()





การใส่ลายบนแท่ง
สามารถใส่ลวดลายลงบนแท่งได้โดยเพิ่มคีย์เวิร์ด hatch รูปแบบลวดลายที่สามารถใส่ได้นั้นมีหลากหลายและสามารถใส่ผสมกันได้
| เส้นแนวตั้ง
- เส้นแนวนอน
+ เส้นตาข่ายแนวตั้งนอน
\ เส้นทแยงเฉียงลง
/ เส้นทแยงเฉียงขึ้น
x เส้นทะแยงตาข่าย
* ดาวห้าแฉก
. จุด
o วงกลมเล็ก
O วงกลมใหญ่

ตัวอย่าง ลองวาดลายในแบบต่างๆออกมาดูเทียบกัน
plt.figure(figsize=[10,5])
plt.axes([0,0,1,1])
lai = ['|','-','+','++++','\\','/','//','\////','x','xx','*','.','...','o','O','.o','.O','ox']
for i in range(len(lai)):
    plt.bar(i,1,hatch=lai[i],color='y')
plt.show()



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



แผนภูมิแท่งในแนวนอน
นอกจาก bar แล้วมีอีกคำสั่งที่ใช้วาดแผนภูมิแท่ง นั่นคือ barh มีการทำงานเหมือนกันแทบทุกอย่างแต่จะต่างกันตรงที่ barh เป็นแผนภูมิแท่งในแนวนอน

ตัวอย่างการใช้
x = np.linspace(1,4,30)
bara = plt.barh(x,1/x**2,height=0.1,ec='k')
for i in range(30):
    bara[i].set_facecolor((0.1,0.03*i,1-0.03*i))
plt.ylim(x.min(),x.max()) # ในที่นี้ขอบเขตของค่า x อยู่ในแกน y
plt.show()



จะเห็นว่าคีย์เวิร์ดที่แทนความกว้างของแท่งนั้นไม่ใช่ width แต่ใช้เป็น height เพราะแผนภูมิถูกวางในแนวนอน



อ้างอิง


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


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

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

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

หมวดหมู่

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

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

目录

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

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

按类别分日志



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

  查看日志

  推荐日志

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