φυβλαςのβλογ
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
モンゴル語
言語学
maya
確率論
日本での日記
中国での日記
-- 北京での日記
-- 香港での日記
-- 澳門での日記
台灣での日記
北欧での日記
他の国での日記
qiita
その他の記事

記事の類別



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

  記事を検索

  おすすめの記事

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

ไทย

日本語

中文