φυβλαςのβλογ
phyblasのブログ



numpy & matplotlib เบื้องต้น บทที่ ๒๔: คัลเลอร์แม็ปและแผนภาพไล่สี
เขียนเมื่อ 2016/06/12 02:52
แก้ไขล่าสุด 2022/07/21 20:31
ในบทที่ผ่านๆมาเราพูดถึงแต่ข้อมูลที่เป็นสองมิติเป็นหลัก แต่ต่อจากนี้ไปจะพูดถึงข้อมูลที่มีมิติเพิ่มขึ้นมาอีกมิติ



แนวความคิดเรื่องการแสดงข้อมูลสามมิติในสองมิติ
ปกติ แล้วการวาดกราฟเส้นคือการแสดงความสัมพันธ์ระหว่างปริมาณ ๒ ค่าว่า เช่นตำแหน่งเทียบกับเวลา (กราฟ t-x) หรือตำแหน่งบนพื้นสองมิติ (กราฟ x-y)

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

แต่ในกรณีที่ต้องการแสดงความสัมพันธ์ระห่างปริมาณ ๓ ค่านั้น ปัญหาจะเพิ่มขึ้นมาอีกมิตินึง

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

ตัวอย่าง สร้างอาเรย์ที่เก็บความสูงตามแนวแกน x และ y โดยสุ่มค่าเอา
import numpy as np
khwamsung = np.random.randint(0,100,(10,10))

ได้
[[96 36 88 85 64 91  0 60 92 11]
 [47 92 76 85 66 16 44 19 62 27]
 [41 40 61 23 63 38 23 38 48 96]
 [65  8 68 62 47 82 76 76 78 17]
 [68 18 21 65 61 58 42 14 99 89]
 [81 59 38 84 60 56 44 91 16 50]
 [29 85 24 52 47  3 14  6 12 88]
 [ 9 87 59 41 53 13 48 58 37 16]
 [80 11  1 30 43 35 55 41 31 28]
 [48 92 18 24 12  2 79 84 73 38]]

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

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

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

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

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

วิธีหนึ่งที่ดีก็คือ การใช้สีแทนตัวค่าความสูง

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

ลองใช้แผนภาพการกระจายที่ได้พูดถึงไปในบทที่ ๑๖ ทำจุดไล่เรียงสี
import random
import matplotlib.pyplot as plt

x = range(10) # ให้ x ไล่ตั้งแต่ 0 ถึง 9
y = [0]*10 # ให้ y เป็น 0 ตลอด เพื่อจะให้จุดอยู่แนวเดียวกัน
c = [(1,random.random(),1) for i in range(10)] # ให้สัดส่วนของสีเขียวเปลี่ยนไปแบบสุ่ม
plt.figure(figsize=(8,2))
plt.scatter(x,y,c=c,s=1500)
plt.show()



จะได้จุดที่มีสีต่างไปตั้งแต่ขาวจนถึงม่วง ถ้าคิดซะว่าความม่วงของจุดแทนส่วนสูงก็จะได้ว่าแผนภาพนี้แสดงความสูงของแต่ละจุด

อย่างไรก็ตาม การต้องมาสร้างลิสต์ของแม่สีทั้งสามแบบนี้ตลอดเพื่อมาใช้นั้นดูแล้วยุ่งยาก

ดังนั้นอาจเป็นการสะดวกที่จะใช้สิ่งที่เรียกว่า คัลเลอร์แม็ป (color map)



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

ใน matplotlib ได้เตรียมฟังก์ชันคัลเลอร์แม็ปเอาไว้หลายตัว สามารถหาได้ด้วยฟังก์ชัน plt.get_cmap

ตัวอย่าง
print(plt.get_cmap('spring')(1.)) # ได้ (1.0, 1.0, 0.0, 1.0)
print(plt.get_cmap('spring')(0.75)) # ได้ (1.0, 0.75294117647058822, 0.24705882352941178, 1.0)
print(plt.get_cmap('spring')(0.5)) # ได้ (1.0, 0.50196078431372548, 0.49803921568627452, 1.0)
print(plt.get_cmap('spring')(0.25)) # ได้ (1.0, 0.25098039215686274, 0.74901960784313726, 1.0)
print(plt.get_cmap('spring')(0.)) # ได้ (1.0, 0.0, 1.0, 1.0)
print(plt.get_cmap('hot')(0.)) # ได้ (0.041599999999999998, 0.0, 0.0, 1.0)

ใน ที่นี้ plt.get_cmap('spring')() คือฟังก์ชันอันหนึ่ง ซึ่งรับค่าตัวเลขเป็นอาร์กิวเมนต์แล้วคืนค่าสีออกมา เลข ๔ ค่าคือ (แดง,เขียว,น้ำเงิน,ความทึบแสง)

ส่วน plt.get_cmap('hot')() ก็เป็นฟังก์ชันคัลเลอร์แม็ปอีกตัวหนึ่ง ใส่ค่าตัวเลขลงไปตัวนึงแล้วก็จะได้เลข ๔ ค่าออกมาเช่นกัน แต่จะต่างจาก spring

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

รายการคัลเลอร์แม็ปทั้งหมด เข้าไปดูแล้วเลือกสีตามที่ต้องการกันได้ http://matplotlib.org/examples/color/colormaps_reference.html

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

ขอบเขตของค่าที่ใส่ ลงในฟังก์ชันคือจำนวนจริงตั้งแต่ 0 ถึง 1 หากลองไล่ค่าในช่วงนี้มาใส่ในฟังก์ชันจะได้ค่าสีที่เปลี่ยนไปเรื่อยๆ แต่ถ้าเกินจาก 1 ไปแล้วค่าจะไม่เปลี่ยนแปลงอีกแล้ว
for c in np.arange(0,1.6,0.1):
    print('%s: %s'%(c,plt.get_cmap('winter')(c)))

ผลลัพธ์
0.0: (0.0, 0.0, 1.0, 1.0)
0.1: (0.0, 0.098039215686274508, 0.9509803921568627, 1.0)
0.2: (0.0, 0.20000000000000001, 0.90000000000000002, 1.0)
0.3: (0.0, 0.29803921568627451, 0.85098039215686272, 1.0)
0.4: (0.0, 0.40000000000000002, 0.80000000000000004, 1.0)
0.5: (0.0, 0.50196078431372548, 0.74901960784313726, 1.0)
0.6: (0.0, 0.59999999999999998, 0.69999999999999996, 1.0)
0.7: (0.0, 0.70196078431372544, 0.64901960784313728, 1.0)
0.8: (0.0, 0.80000000000000004, 0.59999999999999998, 1.0)
0.9: (0.0, 0.90196078431372551, 0.5490196078431373, 1.0)
1.0: (0.0, 1.0, 0.5, 1.0)
1.1: (0.0, 1.0, 0.5, 1.0)
1.2: (0.0, 1.0, 0.5, 1.0)
1.3: (0.0, 1.0, 0.5, 1.0)
1.4: (0.0, 1.0, 0.5, 1.0)
1.5: (0.0, 1.0, 0.5, 1.0)



การนำคัลเลอร์แม็ปมาใช้กับกราฟและแผนภาพ
การใช้คัลเลอร์แม็ปในการวาดกราฟทำได้โดยใส่ฟังก์ชันคัลเลอร์แม็ปที่ต้องการลงในคีย์เวิร์ด cmap ในฟังก์ชันที่ใช้วาด

ขอยกตัวอย่างโดยเอาตัวอย่างที่แล้วมาแก้เล็กน้อยโดยเปลี่ยนค่า c ให้เป็นเลขสุ่มตัวเดียวแทนที่จะเป็นทูเพิลของเลขสีทั้ง ๓ แล้วก็ใส่
x = range(10)
y = [0]*10
c = [random.random() for i in range(10)] # เลขสุ่มในช่วง 0 ถึง 1
plt.figure(figsize=(8,2))
plt.scatter(x,y,c=c,s=1500,cmap=plt.get_cmap('PuRd')) # เพิ่ม cmap เข้าไป
plt.show()



จะพบว่าได้ผลออกมาคล้ายเมื่อกี้ เพราะ PuRd เป็นคัลเลอร์แม็ปที่ไล่สีในโทนขาวแดงชมพู

และจะเห็นว่าง่ายกว่าเดิมเพราะไม่ต้องใส่ค่าตัวเลขแม่สีทั้ง ๓ ตัว แค่ใส่เลขตัวเดียวแล้วมันก็จะเข้าสู่ฟังก์ชันคัลเลอร์แม็ปเพื่อเปลี่ยนเป็น ค่าสีทั้ง ๓ (และค่าความโปร่งใส) ให้โดยอัตโนมัติ

นอกจากนี้จริงๆ แล้ว cmap=plt.get_cmap('PuRd') สามารถย่อเหลือแค่ cmap='PuRd' ได้เลย ถ้าค่าที่ใส่เป็นสายอักขระโปรแกรมจะทำการค้นคัลเลอร์แม็ปที่มีชื่อนี้มาใช้ อยู่แล้ว

ในตัวอย่างนี้เราใส่ค่าสี (c) เป็นเลขในช่วง 0 ถึง 1 แต่ความจริงแล้วค่าสีไม่จำเป็นต้องอยู่ในช่วง 0 ถึง 1 ก็ได้ แม้ว่าค่าของฟังก์ชันคัลเลอร์แม็ปจะมีการเปลี่ยนแปลงเฉพาะในช่วง 0 ถึง 1 ก็ตาม

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

การปรับค่าทั้งหมดให้อยู่ในช่วง 0 ถึง 1 แบบนี้เรียกว่าการนอร์มาไลซ์ (normalize)

ค่านอร์มาไลซ์ = (ค่าเดิม - ค่าต่ำสุด)/(ค่าสูงสุด - ค่าต่ำสุด)

ดังนั้นเราจึงได้ค่าสีที่ไล่จากต่ำสุดจนสูงสุดเสมอ ไม่ต้องมาแปลงเอง

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



การใส่แท่งแถบสี
จากตัวอย่างที่แล้ว เพื่อให้เห็นการไล่เรียงสีชัด คราวนี้ลองเพิ่มแท่งที่มีการไล่เรียงสีตามลำดับเข้าไป
x = range(10)
y = [0]*10
c = [random.random() for i in range(10)]
plt.figure(figsize=(8,2))
plt.axes(ylim=[-4.5,1.5])
plt.scatter(x,y,c=c,s=1500,cmap='PuRd')
plt.scatter(x,[-3]*10,c=x,s=1500,marker='s',cmap='PuRd')
plt.show()

ทำแบบนี้ด้านล่างก็จะได้แท่งที่มีการจัดเรียงสีตามแบบของ PuRd



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

ที่จริงแล้ว matplotlib มีคำสั่งที่สร้างแท่งไล่เรียงสีที่ใช้อธิบายสีในคัลเลอร์แม็ป นั่นคือ plt.colorbar()

ลองพิมพ์ตามนี้เพิ่มเข้าไป
plt.colorbar()

จากนั้นก็จะมีแถบสีปรากฏทางขวา



แถบสีนี้เป็นสิ่งที่ควรใส่ไว้ทุกครั้ง มีความสำคัญเพราะทำให้เข้าใจว่าสีอะไรแทนค่าเท่าไหร่

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

ลองดูตัวอย่างเพิ่มเติม เอาตัวอย่างที่แล้วมาแก้ต่อโดยใช้ numpy แล้วก็เพิ่มเป็นร้อยจุด
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(100)
y = np.zeros(100)
c = np.random.randint(0,100,100)
plt.figure(figsize=(8,2))
sc = plt.scatter(x,y,c=c,s=50,marker='d',cmap='hot')
plt.colorbar()
plt.show()



แถบสีนั้นสามารถปรับแต่งอะไรต่างๆได้มากมายโดยการเติมคีย์เวิร์ดเข้าไป เราจะกลับมาพูดถึงการปรับแต่งแถบสีเพิ่มเติมอีกในบทที่ ๒๖



การเตรียมอาเรย์สองมิติสำหรับแทนพิกัด x,y
หลังจากที่เข้าใจเรื่องคัลเลอร์แม็ปแล้ว และสามารถสร้างแผนภาพไล่สีในหนึ่งมิติได้แล้ว ต่อไปลองมาทำเป็นสองมิติดู

แต่ว่าการทำสองมิตินั้นมีความซับซ้อน เราจำเป็นจะต้องเตรียมอาเรย์ที่เก็บไล่เรียงตำแหน่งในแกน x และ y ไว้ควบคู่กัน ซึ่งวิธีการสร้างก็มีอยู่หลายวิธี

วิธีหนึ่งอาจใช้ tile repeat reshape
x = np.tile(np.arange(10),(10,1))
y = np.repeat(np.arange(10),10).reshape(10,10)
print(x)
print(y)

ได้
[[0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]
 [0 1 2 3 4 5 6 7 8 9]]
[[0 0 0 0 0 0 0 0 0 0]
 [1 1 1 1 1 1 1 1 1 1]
 [2 2 2 2 2 2 2 2 2 2]
 [3 3 3 3 3 3 3 3 3 3]
 [4 4 4 4 4 4 4 4 4 4]
 [5 5 5 5 5 5 5 5 5 5]
 [6 6 6 6 6 6 6 6 6 6]
 [7 7 7 7 7 7 7 7 7 7]
 [8 8 8 8 8 8 8 8 8 8]
 [9 9 9 9 9 9 9 9 9 9]]

จะเห็นว่า x เปลี่ยนค่าไปตามแนวนอน ส่วน y เปลี่ยนค่าไปตามแนวตั้ง แต่จะเหมือนเดิมตลอดในอีกแนว

นี่คืออาเรย์ที่เราต้องการ มีไว้ใช้แทนพิกัดในแกน x และ y สำหรับในแต่ละจุด



ที่จริงในมอดูลมาตรฐานของไพธอนก็มีฟังก์ชันที่ช่วยให้ทำอะไรในลักษณะนี้ออกมา ได้ นั่นคือฟังก์ชัน product ในมอดูล itertools ซึ่งอธิบายไว้ในบทความภาษาไพธอนเบื้องต้นบทที่ ๒๘

เพียงแต่ว่าผลที่ได้จะอยู่ในรูปหนึ่งมิติ ต้องมาแปลงเป็นอาเรย์แล้ว reshape อีกที
import itertools
xy = list(itertools.product(range(10),range(10)))
print(xy) # ได้ [(0, 0), (0, 1), (0, 2), (0, 3),...
x,y = np.array(xy).T.reshape(2,10,10)

ทำแบบนี้ก็จะได้ x กับ y เหมือนกันกับตัวอย่างที่แล้ว

แต่มีวิธีที่ทำได้ง่ายกว่าและนิยมมากกว่า นั่นคือการใช้ฟังก์ชัน np.meshgrid

หากเขียนเป็น
x,y = np.meshgrid(np.arange(10),np.arange(10))

ก็จะได้ x,y ในลักษณะแบบเดียวกับตัวอย่างข้างต้น

ฟังก์ชัน np.meshgrid มีไว้สำหรับสร้างลิสต์ของอาเรย์ที่แจกแจงค่า โดยออกมาในรูปของอาเรย์ที่มีมิติตามจำนวนอาร์กิวเมนต์ที่ใส่เข้าไป

ในที่นี้ใส่อาร์กิวเมนต์เป็น np.arange(10) ไป ๒ ตัว ซึ่ง ๒ ตัวนี้แทนแกน x และ y ผลที่ได้คือฟังก์ชันนี้จะคืนค่าอาเรย์ 10x10 มา ๒ ตัว ตัวแรกคือค่าของแกน x ตัวหลังคือของแกน y จากนั้นเราก็ใช้ตัวแปร x กับ y มารับค่าทั้งสองนี้

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

ทีนี้เมื่อได้โครงข่าย x และ y ตามที่ต้องการมาแล้วเราก็สร้างอาเรย์แทนความสูงซึ่งมีจำนวนแถวและหลักเท่ากันมา
z = np.random.randint(0,100,(10,10))
print(z)

ได้
[[93 43 63 56 68 71 15 16 40 16]
 [25 42 64  5 14 61 49 77 81 34]
 [77  1 78 96 93 81 11 33 45 26]
 [84 61 95 61  6 86 74 31 45 67]
 [10 28 73  4  9 34  2 34 37 70]
 [33  8 99 20 78 50 24  7 81 57]
 [56 62 16 69 64 44 14 49 78 92]
 [31 87 25 29 97 12 69 78 65 68]
 [12 67 23 82 32 37 25 23 13 83]
 [94 93 79 10  5  3 15 10 42 74]]

ลองนำมาเรียงต่อกันดูจะทำให้เห็นภาพขึ้น ในที่นี้อันบนสุดคืออาเรย์แทนความสูง และสองอันล่างคือพิกัดในแกน x และ y



เท่านี้ส่วนประกอบที่เราต้องการนำมาใช้วาดแผนภาพไล่สีก็พร้อมแล้ว

ต่อมาลองนำมาใช้วาดกราฟการแจกแจงเพื่อแสดงความสูงของพื้นที่ในสองมิติกันดูเลย
x,y = np.meshgrid(np.arange(10),np.arange(10)) # สร้างโครงข่ายแกน x และ y
khwamsung = np.random.randint(0,100,(10,10)) # สุ่มความสูงในช่วง 0 ถึง 99
plt.axes(aspect=1,xlim=[-1,10],ylim=[-1,10])
plt.scatter(x,y,c=khwamsung,s=600,marker='s',cmap='BuGn') # ใช้สีโทนเขียว
plt.colorbar() # ใส่แถบสีทางขวา
plt.show()





ต่อมาขอลองยกตัวอย่างใหม่ คราวนี้ลองเพิ่มความละเอียดเป็นร้อยแล้วให้ค่าความสูงเป็นค่าที่ได้จากการคำนวณ โดยใช้เป็นฟังก์ชันพาราโบลาซึ่งมีค่าต่ำสุดที่จุด 0,0 ที่ใจกลาง
x,y = np.meshgrid(np.linspace(-4,4,100),np.linspace(-4,4,100))
z = x**2+y**2 # ค่าความสูงเป็นพาราโบลา
plt.axes(xlim=[-4,4],ylim=[-4,4]) # กำหนดขอบเขตให้อยู่ในช่วง -4 ถึง 4
plt.scatter(x,y,c=z,s=15,marker='s',cmap='jet',lw=0) # วางจุด
plt.colorbar()
plt.show()





การสร้างแผนภาพไล่สี
แม้ว่า scatter จะใช้ทำแผนภาพไล่สีได้ แต่จริงๆแล้วมันไม่ได้ถูกออกแบบมาเพื่อการนี้โดยเฉพาะ มีอีกวิธีที่เหมาะกว่า นั่นคือใช้ฟังก์ชัน pcolor

ฟังก์ชันนี้มีไว้ระบายสีพื้นตามสีที่กำหนดในตำแหน่งต่างๆ การใช้ก็คล้ายๆกับ scatter ใส่อาร์กิวเมนต์สองตัวแรกเป็นแกน x และ y และตัวที่ ๓ ใส่ค่าสี

ลองแทนโค้ดตัวอย่างที่แล้ว บรรทัด plt.scatter ด้วย pcolor
plt.pcolor(x,y,z,cmap='jet')

ผลที่ได้จะแทบไม่ต่างจากเดิม

แต่ pcolor นั้นเมื่อใช้แล้วพื้นสีจะกระจายทั่วฉากเสมอ จะวางตำแหน่งจุดห่างแค่ไหนก็ได้

ถ้าวางจำนวนจุดน้อยก็จะเห็นเป็นเหมือนภาพที่ความละเอียดต่ำ

จะให้แนวตั้งและนอนมีความละเอียดไม่เท่ากันก็ได้ ตัวอย่างเช่น
x,y = np.meshgrid(np.linspace(-40,40,13),np.linspace(-40,40,50))

z = x**2+y**2

plt.pcolor(x,y,z,cmap='rainbow')
plt.colorbar()
plt.show()



หากต้องการจะแบ่งให้ไม่เท่ากันก็สามารถทำได้เช่นกัน

ตัวอย่างเช่น ลองให้ความกว้างช่องเพิ่มขึ้นเรื่อยๆเมื่อไกลจากตรงกลาง
x,y = np.meshgrid(np.linspace(-2,2,50)**3,np.linspace(-2,2,50)**3)

z = x**2+y**2

plt.pcolor(x,y,z,cmap='rainbow')
plt.colorbar()
plt.show()



ซึ่งตรงจุดนี้จะเห็นข้อแตกต่างระหว่าง pcolor กับ scatter ได้ชัดเมื่อลองดูข้อมูลที่มีความไม่ต่อเนื่อง เช่น
x,y = np.meshgrid(np.linspace(0,20,100),np.hstack((np.linspace(-20,5,100),np.linspace(15,20,50))))
z = x**2+y**2
plt.subplot(121,xlim=[0,20],ylim=[-20,20])
plt.scatter(x,y,c=z,marker='s',lw=0,cmap='gnuplot2')
plt.subplot(122,xlim=[0,20],ylim=[-20,20])
plt.pcolor(x,y,z,cmap='gnuplot2')
plt.show()



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



ในกรณีที่ต้องการให้สีแบ่งสม่ำเสมอนั้น pcolor ยังสามารถละ x,y ได้ด้วย โดยใส่อาร์กิวเมนต์เป็นสี (ความสูง) อย่างเดียวได้เลย แล้วพิกัดที่ได้จะถูกคิดตามตำแหน่งภายในอาเรย์ของอาเรย์ที่เก็บสี

ตัวอย่าง
x,y = np.meshgrid(np.linspace(-4,4,100),np.linspace(-4,4,100))
z = x**2+y**2
plt.pcolor(z,cmap='rainbow')
plt.colorbar()
plt.show()



นอกจากนี้ยังเพิ่มเส้นกั้นแต่ละช่องลงไปได้ด้วยคีย์เวิร์ด edgecolor โดยใส่ค่าสีลงไป และกำหนดความหนาของเส้นด้วยคีย์เวิร์ด linewidths

ลองแก้เป็น
plt.pcolor(z,cmap='rainbow',edgecolors='#222222',linewidths=0.5)

จะออกมาแบบนี้





นอกจากฟังก์ชัน pcolor แล้วก็ยังมี pcolormesh อีกตัวที่ทำงานคล้ายกันมาก แต่ก็มีความต่างกันเล็กน้อย โดยหลักๆแล้วก็คือ pcolormesh ทำงานเร็วกว่ามาก ดังนั้นโดยทั่วไปหากแผนภาพที่จะวาดมีความละเอียดมากต้องใช้เวลาวาดนานก็อาจควรเลือกใช้ pcolormesh แทน pcolor

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



อ้างอิง


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


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

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

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

หมวดหมู่

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

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

目次

日本による名言集
モジュール
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
機械学習
-- ニューラル
     ネットワーク
javascript
モンゴル語
言語学
maya
確率論
日本での日記
中国での日記
-- 北京での日記
-- 香港での日記
-- 澳門での日記
台灣での日記
北欧での日記
他の国での日記
qiita
その他の記事

記事の類別



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

  記事を検索

  おすすめの記事

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

ไทย

日本語

中文