φυβλαςのβλογ
บล็อกของ 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
ภาษา 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月

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

ไทย

日本語

中文