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



numpy & matplotlib เบื้องต้น บทที่ ๓๒: อาเรย์แนวทแยง และอาเรย์สามเหลี่ยม
เขียนเมื่อ 2016/06/12 13:03
แก้ไขล่าสุด 2021/09/28 16:42
เมทริกซ์แนวทแยงอีกทั้งเมทริกซ์สามเหลี่ยมเป็นเมทริกซ์รูปแบบหนึ่งที่มีคุณสมบัติพิเศษมักถูกใช้งานบ่อย

numpy จึงมีการเตรียมวิธีต่างๆในการสร้างอาเรย์ที่แทนเมทริกซ์แนวทแยงและเมทริกซ์สามเหลี่ยมไว้

ในบทที่ ๒ ได้พูดถึงฟังก์ชัน np.eye กับ np.identity ไปแล้ว นั่นก็เป็นอาเรย์แนวทแยงในรูปแบบหนึ่ง สำหรับในบทนี้จะพูดถึงฟังก์ชันอื่นๆที่เหลือ



อาเรย์แนวทแยงใดๆสามารถสร้างได้โดยใช้ np.diag โดยใส่ลิสต์ของสมาชิกแนวทแยงที่ต้องการลงไปเป็นอาร์กิวเมนต์

ตัวอย่าง
import numpy as np
print(np.diag([3,3,9]))

ได้
[[3 0 0]
 [0 3 0]
 [0 0 9]]

ค่าที่ใช้ใน np.diag จะเป็นอาเรย์ก็ได้ เช่นลองใช้ร่วมกับ np.arange ดูก็จะได้อาเรย์แนวทแยงที่มีค่าเรียงกันไป
print(np.diag(np.arange(4,8)))

ได้
[[4 0 0 0]
 [0 5 0 0]
 [0 0 6 0]
 [0 0 0 7]]

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

ตัวอย่าง
print(np.diag(np.arange(4,8),1))
print(np.diag(np.arange(4,8),-2))

ได้
[[0 4 0 0 0]
 [0 0 5 0 0]
 [0 0 0 6 0]
 [0 0 0 0 7]
 [0 0 0 0 0]]
[[0 0 0 0 0 0]
 [0 0 0 0 0 0]
 [4 0 0 0 0 0]
 [0 5 0 0 0 0]
 [0 0 6 0 0 0]
 [0 0 0 7 0 0]]

นอกจากนี้ก็มีฟังก์ชัน np.diagflat ซึ่งคล้ายกับ np.diag แต่อาเรย์หรืิอลิสต์ที่ใส่จะมีกี่มิติก็ได้ จะถูกยุบให้เหลือมิติเดียวโดยอัตโนมัติ
print(np.diagflat([[1,7], [4,6]]))

ได้
[[1 0 0 0]
 [0 7 0 0]
 [0 0 4 0]
 [0 0 0 6]]



การดึงสมาชิกแนวทแยงจากอาเรย์สองมิติ
ฟังก์ชัน np.diag นั้นนอกจากจะใช้สำหรับสร้างเมทรกซ์แนวทแยงแล้วยังมีอีกความสามารถหนึ่ง นั่นคือหากใช้กับอาเรย์สองมิติก็จะเป็นการนำเอาสมาชิกในแนวทแยงออกมาสร้าง เป็นอาเรย์ใหม่

ตัวอย่าง
x = np.arange(7,27).reshape(4,5)
print(x)
print(np.diag(x))

ได้
[[ 7  8  9 10 11]
 [12 13 14 15 16]
 [17 18 19 20 21]
 [22 23 24 25 26]]
[ 7 13 19 25]

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

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

ตัวอย่าง ใช้อาเรย์ x จากตัวอย่างที่แล้ว
print(np.diag(x,1)) # ได้ [ 8 14 20 26]
print(np.diag(x,2)) # ได้ [ 9 15 21]
print(np.diag(x,3)) # ได้ [10 16]
print(np.diag(x,-1)) # ได้ [12 18 24]

แต่ว่าอาเรย์ที่ได้มาจากตรงนี้จะเป็นอาเรย์มุมมองเท่านั้น ต่อให้เอาตัวแปรมารับค่าก็ไม่สามารถแก้ไขเปลี่ยนแปลงค่าอะไรในตัวแปรนั้นได้
x2 = np.diag(x,-1)
x2[0] = 999 # ได้ ValueError: assignment destination is read-only

หากต้องการสร้างอาเรย์ใหม่ที่แก้ค่าได้ก็ต้องใช้ copy
x2 = np.diag(x,-1).copy()
x2[0] = 999
print(x2) # ได้ [999  18  24]



การแก้ไขสมาชิกในแนวทแยง
แม้ว่า np.diag จะดึงมุมมองในแนวทแยงของอาเรย์ออกมาได้แต่ว่าก็แค่เพื่อดูค่า เราไม่สามารถแก้ไขค่าอะไรในแนวทแยงของอาเรย์นั้นได้

หากต้องการเปลี่ยนแปลงแก้ไขค่าในแนวทแยงของอาเรย์ก็อาจทำได้โดยใช้ np.fill_diagonal

ตัวอย่าง
x = np.ones([5,4])
print(x)
np.fill_diagonal(x,[3,4,5,7])
print(x)

ได้
[[ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]]
[[ 3.  1.  1.  1.]
 [ 1.  4.  1.  1.]
 [ 1.  1.  5.  1.]
 [ 1.  1.  1.  7.]
 [ 1.  1.  1.  1.]]

ถ้าใส่เป็นตัวเลขตัวเดียวก็จะเป็นการใส่แทนด้วยตัวเลขนั้นทั้งหมด
np.fill_diagonal(x,0)
print(x)

ได้
[[ 0.  1.  1.  1.]
 [ 1.  0.  1.  1.]
 [ 1.  1.  0.  1.]
 [ 1.  1.  1.  0.]
 [ 1.  1.  1.  1.]]



การดึงสมาชิกแนวทแยงจากอาเรย์สามมิติ
มีอีกฟังก์ชันที่ใช้ดึงสมาชิกแนวทแยงของอาเรย์สองมิติออกมาได้เช่นเดียวกัน คือ np.diagonal หากใช้กับอาเรย์สองมิติจะให้ผลเหมือนกับ np.diag

อย่างไรก็ตาม np.diagonal สามารถใช้กับอาเรย์สามมิติขึ้นไปได้ด้วย ในขณะที่ np.diag ใช้กับอาเรย์หนึ่งหรือสองมิติเท่านั้น

ตัวอย่างการใช้
x = np.arange(3*3*4).reshape(3,3,4)



print(np.diagonal(x))

ได้
[[ 0 16 32]
[ 1 17 33]
[ 2 18 34]
[ 3 19 35]]

จะเห็นว่า np.diagonal จะทำการหาเมทริกซ์แนวทแยงโดยคิดตามด้านสูงและด้านลึก แต่แยกแต่ละหลักในแนวซ้ายขวาคิดต่างหากกัน

หาก ต้องการให้เปลี่ยนแนวในการคิดก็ทำได้โดยการใส่คีย์เวิร์ด axis1 กับ axis2 ลงไป เป็นเลขของแกนที่ต้องการ ค่าตั้งต้นคือ axis1=0 และ axis1=2

ลองสลับแกนอื่นนอกจากค่าตั้งต้นดูก็จะได้ผลที่ต่างออกไป
print(np.diagonal(x,axis1=0,axis2=2))
print(np.diagonal(x,axis1=1,axis2=2))

ได้
[[ 0 13 26]
 [ 4 17 30]
 [ 8 21 34]]
[[ 0  5 10]
 [12 17 22]
 [24 29 34]]



การหาผลรวมตลอดแนวทแยง
ในการหาผลรวมตลอดแนวทแยงนั้นสามารถทำได้ โดยใช้ np.trace

กรณีใช้กับสองมิติจะเป็นการบวกสมาชิกทั้งหมดที่มีเลขแถวและหลักเท่ากัน เช่น
x = np.arange(12,24).reshape(3,4)
print(x)
print(np.trace(x))

ได้
[[12 13 14 15]
 [16 17 18 19]
 [20 21 22 23]]
51

ถ้าหากต้องการผลรวมของสมาชิกที่ไม่ใช่แนวแกนกลางพอดีแต่เลื่อนออกไปก็ทำได้โดย ใส่อาร์กิวเมนต์ตัวที่สอง เช่นเดียวกับ diag หรือ diagonal
print(np.trace(x,1)) # ได้ 54
print(np.trace(x,-2)) # ได้ 20

กรณี ที่ใช้กับสามมิติจะคิดแยกทีละคู่แกน ลักษณะเดียวกับ np.diagonal อาจถือว่า np.trace(x) มีค่าเท่ากับ np.sum(np.diagonal(x),axis=1)
x = np.arange(21,48).reshape(3,3,3)
print(np.trace(x))

ได้
[ 99 102 105]



การสร้างอาเรย์สามเหลี่ยม
เมทริกซ์สามเหลี่ยมคืออาเรย์ที่มีสมาชิกที่มีค่าไม่ใช่ 0 อยู่แค่ไม่เกินไปจากแนวทแยง ที่เหลือเป็น 0

เมทริกซ์สามเหลี่ยมมีสองแบบคือสามเหลี่ยมบนและสามเหลี่ยมล่าง

เราสามารถสร้างอาเรย์แทนเมทริกซ์สามเหลี่ยมบนได้จากฟังก์ชัน np.triu โดยใช้อาเรย์ที่มีอยู่เดิมมาตัดสมาชิกส่วนที่อยู่แถวล่างออกให้เป็น 0

และอาเรย์แทนเมทริกซืสามเหลี่ยมล่างก็สามารถสร้างได้ในทำนองเดียวกันโดยใช้ ฟังก์ชัน np.tril แต่ต่างกันตรงที่ np.tril จะทำให้ด้านบนเป็น 0 แทน

ตัวอย่าง
x = np.arange(10,19).reshape(3,3)
print(x)
print(np.triu(x))
print(np.tril(x))

ได้
[[10 11 12]
 [13 14 15]
 [16 17 18]]
[[10 11 12]
 [ 0 14 15]
 [ 0  0 18]]
[[10  0  0]
 [13 14  0]
 [16 17 18]]

หากใส่อาร์กิวเมนต์ตัวที่สองจะเป็นการเลื่อนแถวที่พิจารณาเป็นขอบเขต
print(np.triu(x,1))
print(np.tril(x,1))

ได้
[[ 0 11 12]
 [ 0  0 15]
 [ 0  0  0]]
[[10 11  0]
 [13 14 15]
 [16 17 18]]

นอกจากนี้ยังมีฟังก์ชัน tri สำหรับสร้างอาเรย์สามเหลี่ยมล่างที่มีสมาชิกเป็น 1 ล้วนขึ้นมาใหม่

ถ้าใส่อาร์กิวเมนต์ไปตัวเดียวจะได้อาเรย์สามเหลี่ยมล่างที่มีจำนวนแถวและหลักตามค่านั้น
x = np.tri(3)
print(x)

ได้
[[ 1.  0.  0.]
 [ 1.  1.  0.]
 [ 1.  1.  1.]]

แต่ถ้าใส่สองตัวก็จะได้จำนวนแถวตามเลขแรกและจำนวนหลักตามเลขหลัง
x = np.tri(3,4)
print(x)

ได้
[[ 1.  0.  0.  0.]
 [ 1.  1.  0.  0.]
 [ 1.  1.  1.  0.]]

หากใส่อาร์กิวเมนต์ตัวที่สาม จะเป็นการเลื่อนแถวที่พิจารณาเป็นขอบเขต
x = np.tri(3,4,-1)
print(x)

ได้
[[ 0.  0.  0.  0.]
 [ 1.  0.  0.  0.]
 [ 1.  1.  0.  0.]]



อ้างอิง


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


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

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

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

หมวดหมู่

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

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

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- 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月

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

ไทย

日本語

中文