NumPy
NumPy
เมื่อจบหัวข้อนี้ ผู้เรียนควรจะ
√ CLO2: เลือกใช้ตัวแปร ชนิดข้อมูล คำสั่งเงื่อนไข คำสั่งทำซ้ำ และไลบรารีมาตรฐานในการเขียนโปรแกรมได้อย่างเหมาะสม
เรียกใช้งานไลบรารี Numpy เพื่อคำนวณงานที่ใช้ vector และ matrix
สร้างกราฟอย่างง่ายจากข้อมูล Numpy array
√ CLO5: เขียนโปรแกรมเพื่อแก้ปัญหาทางด้านคณิตศาสตร์ สถิติ และปัญหาในชีวิตประจำวัน
เขียนโปรแกรมเพื่อแก้ปัญหาโจทย์ โดยเรียกใช้ Numpy
√ CLO6: ทดสอบโปรแกรม ค้นหาจุดบกพร่อง และแก้ไขให้โปรแกรมทำงานถูกต้อง
ทดสอบโปรแกรมที่ใช้ไลบารี Numpy
ค้นหาจุดบกพร่อง (bug) และแก้ไข (debug) ให้ฟังก์ชันทำงานถูกต้อง
การคำนวณเชิงตัวเลข (Numerical computing) เป็นการคำนวณทางคณิตศาสตร์เพื่อใช้ในการแก้ปัญหาทางวิทยาศาสตรและวิศวกรรมศาสตร์ เน้นการประมวลผลกับข้อมูลตัวเลข เช่น การแก้สมการ การหาค่าฟังก์ชัน การจำลองโมเดล การหาค่าทางสถิติ การสร้างกราฟ ในภาษา Python ไลบรารีที่เหมาะสำหรับงานประเภทนี้ คือ NumPy เพราะมีโครงสร้างข้อมูลและฟังก์ชันที่จัดการกับข้อมูลหลายๆ ค่าพร้อมกันได้
โครงสร้างข้อมูลที่จัดเก็บใน NumPy เรียกว่าอาเรย์ n มิติ (ndarray) มีลักษณะคล้ายกับลิสต์
ต่างกันที่ข้อมูลแต่ละค่าต้องเป็นชนิดข้อมูลเดียวกัน ทำให้เหมาะสำหรับการคำนวณข้อมูลทุกค่าพร้อมกันในครั้งเดียว เช่น เวกเตอร์ (1D array) เมทริกซ์ (2D array) หรือข้อมูล 3 มิติ (3D array)
ndarray ทำงานได้เร็วกว่าลิสต์ และใช้พื้นที่ในหน่วยความจำน้อยกว่า
อ่านเพิ่มเติมที่ https://numpy.org/doc/stable/user/absolute_beginners.html
เมื่อเริ่มใช้ NumPy ต้องใช้คำสั่ง import ก่อน โดยนิยมตั้งชื่อให้ใหม่ว่า np
import numpy as np
การสร้างอาเรย์โดย np.array()
ใช้ฟังก์ชัน np.array() โดยระบุพารามิเตอร์เป็นลิสต์ หรือลิสต์ซ้อนลิสต์ได้
รูปแบบคำสั่ง
var_name = np.array(list)
การสร้างอาเรย์โดยใช้ฟังก์ชัน
np.arange(start, stop, step) สร้าง vector จากโดยค่าเริ่มที่ start เพิ่มขึ้นทีละ step และค่าสุดท้ายน้อยกว่า stop คล้ายกับฟังก์ชัน range() แต่พารามิเตอร์แต่ละตัวเป็นเลขทศนิยมได้
np.zeros(shape) สร้างอาเรย์ที่ค่าทุกตัวเป็น 0 ตามขนาดที่ระบุใน shape ถ้าเป็นอาเรย์หลายมิติ ระบุ shape ในทูเพิล
np.ones(shape) สร้างอาเรย์ที่ค่าทุกตัวเป็น 1 ตามขนาดที่ระบุใน shape
np.identity(n) สร้างอาเรย์ 2 มิติ ขนาด n x n ที่ค่าทุกตัวในแนวทะแยงมุมเป็น 1
np.diag(x) ถ้า x เป็นอาเรย์ 2 มิติ จะได้ vector ที่มีค่าทุกตัวในแนวทะแยงมุมของ x แต่ถ้า x เป็น vector จะได้อาเรย์ 2 มิติที่มีค่าแนวทะแยงมุมเป็นค่าของ x และค่าที่เหลือจะเป็น 0
np.concatenate((a,b)) สร้างอาเรย์ใหม่จากอาเรย์ a และ b โดยนำมาต่อกัน
คุณลักษณะของอาเรย์
ndarray.ndim ระบุจำนวนมิติของอาเรย์
ndarray.size ระบุจำนวนข้อมูลทุกตัวในอาเรย์
ndarray.shape ระบุจำนวนข้อมูลในแต่ละมิติของอาเรย์ในรูปแบบทูเพิล เช่น shape (2, 3) คือ อาเรย์ 2 มิติขนาด 2 แถว 3 คอลัมน์
(ndarray คือ ชื่อตัวแปร numpy array)
ตัวอย่างคำสั่ง
print(a.ndim) # 1
print(b.ndim) # 2
print(c.shape) # (4,)
print(d.shape) # (3,2)
print(e.size) # 6
print(h.size) # 9
🌟 ข้อสังเกตเมื่อสั่งพิมพ์ข้อมูลในอาเรย์
แสดงในเครื่องหมาย [ ] เช่นเดียวกับลิสต์
ไม่มีเครื่องหมายคอมมา "," คั่นระหว่างแต่ละค่า
สำหรับข้อมูล 2 มิติ จะแสดงข้อมูลแต่ละแถวคนละบรรทัดกัน
กรณีเลขทศนิยมที่หลังจุดทศนิยมเป็น 0 จะแสดงแค่เลขจำนวนเต็มตามด้วยจุด
ตัวอย่างการสร้างอาเรย์ (create_arr.py)
import numpy as np
a = np.array([1,2,3]) # 1D array
print(a) # [1 2 3]
print(type(a)) # <class 'numpy.ndarray'>
b = np.array([[1,2,3],
[4,5,6],
[7,8,9]]) # 2D array
print(b) # [[1 2 3]
# [4 5 6]
# [7 8 9]]
c = np.zeros(4)
print(c) # [0. 0. 0. 0.]
d = np.ones((3,2))
print(d) # [[1. 1.]
# [1. 1.]
# [1. 1.]]
e = np.arange(6)
print(e) # [0 1 2 3 4 5]
f = np.arange(0, 2, 0.5)
print(f) # [0. 0.5 1. 1.5]
g = np.diag(b)
print(g) # [1 5 9]
h = np.diag(g) # [[1 0 0]
print(d) # [0 5 0]
# [0 0 9]]
i = np.identity(2)
print(i) # [[1. 0.]
# [0. 1.]]
j = np.concatenate((a,g))
print(j) # [1 2 3 1 5 9]
รับข้อมูลขนาด n ค่า ใส่ในอาเรย์ 1 มิติ
import numpy as np
nums = [int(n) for n in input().split()]
#nums = list(map(int, input().split()))
print(nums, type(nums))
vector = np.array(nums)
print(vector, type(vector))
print(vector.shape)
print(vector.ndim)
print(vector.size)
Output
2 1 1 1 1
[2 1 1 1 1]
Output
1 2 3
[ 1 2 3]
คำสั่งรับข้อมูลจากผู้ใช้ K แล้วรับข้อมูลขนาด K rows x N columns ใส่ในอาเรย์ 2 มิติ
import numpy as np
K = int(input())
# input 2D array, K rows x N columns
arr = []
for i in range(K):
row = list(map(int, input().split()))
arr.append(row)
arr = np.array(arr)
print(arr)
Output
5
2 1 1 1 1
3 2 1 1 1
3 3 2 1 1
3 3 3 2 1
3 3 3 3 2
[[2 1 1 1 1]
[3 2 1 1 1]
[3 3 2 1 1]
[3 3 3 2 1]
[3 3 3 3 2]]
Output
4
1 2 3
4 5 6
7 8 9
10 11 12
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
อ้างถึงโดยใช้ index และ slice เช่นเดียวกับลิสต์ สำหรับอาเรย์ n มิติ จะอ้างถึง index ของแต่ละมิติได้โดยคั่นด้วยเครื่องหมายคอมมา ',' เช่น จากรูปด้านล่าง
อาเรย์ 1 มิติ
data[0:2] หมายถึง ข้อมูลตำแหน่งที่ 0 และ 1 คือค่า [1 2]
อาเรย์ 2 มิติ
data[0:2] หมายถึง ข้อมูลทุกคอลัมน์ของแถวที่ 0 และ 1 คือ array([[1, 2, 3, 4], [5, 6, 7, 8]])
data[0, 1] หมายถึง ข้อมูลของแถวที่ 0 คอลัมน์ที่ 1 คือค่า 2 (เป็นค่าเดียวไม่ใช่อาเรย์)
data[0:2, 0] หมายถึง ข้อมูลของแถวที่ 0 และ 1 เฉพาะคอลัมน์ที่ 0 คือ array([1, 3])
1D Array
2D Array
ตัวอย่าง (index_1darr.py)
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(a[1]) # 2
print(a[0:2]) # [1 2]
print(a[7:]) # [8 9 10]
print(a[-2:]) # [9 10]
arr1 = a[3:8]
print(arr1) # [4 5 6 7 8]
print(a[a % 3 == 0]) # [3 6 9]
arr2 = a[a < 0]
print(arr2) # []
arr3 = a[a > 6]
print(arr) # [ 7 8 9 10]
สังเกตว่าเราสามารถอ้างถึงข้อมูลในอาเรย์โดยระบุเงื่อนไขแทน index ได้ใช้สำหรับเลือกข้อมูลบางตัวในอาเรย์ที่ตรงตามเงื่อนไข เช่น
a[a > 5] ข้อมูลในอาเรย์ a โดยเลือกเฉพาะที่มีข้อมูลที่มีค่ามากกว่า 5
b[(b > 2) & (b < 11)] ข้อมูลในอาเรย์ b ที่มีค่าอยู่ระหว่าง 2-11
ตัวอย่าง (index_2darr.py)
b = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(b[0,1]) # 2
print(b[1:3]) # [[ 5 6 7 8]
# [ 9 10 11 12]]
print(b[0:2, 0]) # [1 5]
print(b[2]) # [ 9 10 11 12]
arr2 = b[:, 1]
print(arr2) # [2 6 10]
arr3 = b[b < 5]
print(arr3) # [1 2 3 4]
arr4 = b[(b > 2) & (b < 11)]
print(arr4) # [3 4 5 6 7 8 9 10]
arr5 = b[b % 2 == 0]
print(arr5) # [2 4 6 8 10 12]
เราสามารถใช้ตัวดำเนินพื้นฐานต่างๆ กับอาเรย์ได้เช่นกัน โดยการดำเนินการระหว่างอาเรย์จะเป็นการคำนวณแบบตำแหน่งที่ตรงกัน (element-wise)
ตัวอย่าง (op_arr.py)
data = np.array([1, 2])
ones = np.ones(2, dtype=int)
print(data + ones) # array([2, 3])
print(data - ones) # array([0, 1])
print(data * data) # array([1, 4])
print(data / data) # array([1., 1.])
ตัวอย่าง
data = np.array([[1, 2], [3, 4]])
ones = np.array([[1, 1], [1, 1]])
print(data + ones) # array([[2, 3],[4, 5]])
ถ้าการเรียกใช้ฟังก์ชันกับอาเรย์จะเป็นการใช้ฟังก์ชันกับข้อมูลแต่ละค่าในอาเรย์ ฟังก์ชันที่นิยมใช้งานกับอาเรย์ เช่น min, max, sum, mean, std, argmax, argmin (คืนตำแหน่งค่ามาก/น้อยสุด)
กรณีที่เป็นอาเรย์ 2 มิติ ฟังก์ชันเหล่านี้สามารถระบุพารามิเตอร์ axis เพื่อจะใช้ฟังก์ชันกับข้อมูลในแถวหรือคอลัมน์อย่างเดียวได้ โดย axis = 0 คือ ใช้ฟังก์ชันกับข้อมูลคอลัมน์ (แกนตั้ง) และ axis = 1 คือทำกับข้อมูลแต่ละแถว (แนวนอน) แต่ถ้าไม่ระบุแกนจะดำเนินการกับข้อมูลทั้งหมด
นอกจากนี้ยังสามารถใช้ตัวดำเนินการเปรียบเทียบกับอาเรย์ เพื่อตรวจสอบว่าข้อมูลตำแหน่งใดที่ตรงกับเงื่อนไข โดยจะคืนค่าเป็น True/False ในตำแหน่งนั้น
ตัวอย่าง (op_arr.py)
a = np.array([1, 2, 3, 4])
print(a.sum()) # 10
print(a.mean()) # 2.5
print(a.max()) # 4
b = np.array([[1, 2], [5, 3], [4, 6]])
print(b.sum()) # 21
print(b.max(axis=0)) # array([5, 6])
print(b.max(axis=1)) # array([2, 5, 6])
sum_col = b.sum(axis=0) # array([10, 11])
sum_row = b.sum(axis=1) # array([3, 8, 10])
print(b.T) # transpose matrix b
c = np.array([3, 2, 1, 8, 5, 6, 7, 4])
print(c.argmax()) # 3 (index of maximum value - 8)
print(c[c % 2 == 0].sum()) # 20 (2+8+6+4)
print(c > 5) # [False False False True False True True False]
print(sum(c > 5)) # 3 (count only True)
ฟังก์ชันเกี่ยวกับเวกเตอร์/เมทริกซ์
arr.T หรือ arr.transpose() คำสั่ง Transpose เมทริกซ์
x.reshape(shape) เปลี่ยน shape ของอาเรย์
x.dot(y) หรือ np.dot(x,y) คำนวณ dot product ของเวกเตอร์/เมทริกซ์
np.flip(x) กลับค่าในอาเรย์ (reverse)
ตัวอย่าง (reshape_arr.py)
data = np.array([[1, 2], [3, 4], [5, 6]])
print(data.transpose()) # [[1 3 5]
[2 4 6]]
print(data.T) # same
arr1 = np.arange(1,7).reshape((2,3))
print(arr1) # [[1 2 3]
# [4 5 6]]
arr2 = np.arange(1,7).reshape((3,2))
print(arr2) # [[1 2]
# [3 4]
# [5 6]]
arr3 = arr1.dot(arr2) # [[22 28]
# [49 64]]
print(np.matmul(arr1,arr2)) # same
print(np.flip(arr2)) # [[6 5]
# [4 3]
# [2 1]]
การดำเนินการระหว่างอาเรย์ที่มีขนาดไม่เท่ากัน NumPy จะขยายอาเรย์ให้มีขนาดเท่ากันก่อนอัตโนมัติ (broadcasting) โดยพิจารณาว่าถ้ามิติใดมีจำนวนเท่ากันแล้วให้ขยายขนาดอีกมิติให้เท่ากันด้วย ดังตัวอย่าง
ตัวอย่าง (broadcast_arr.py)
data = np.array([[1, 2], [3, 4], [5, 6]]) # shape (3,2)
ones_row = np.array([[1, 1]]) # shape (1,2) -> broadcasting to (3,2)
print(data.shape, ones_row.shape) # (3, 2) (1, 2)
print(data + ones_row)
ทดลองสร้างอาเรย์แล้วดำเนินการบวกกัน และสังเกตการ broadcast แล้ววาดรูปแสดงการทำงานดังตัวอย่างรูปด้านบน
[ [1 2 3] + [9 8 7]
[4 5 6]]
[ [1 2 3] ] + [ [6]
[7]]
[ [1 2 3] + 9
[4 5 6]]
[ [1 2 3] + [[1]
[4 5 6]] [1]]
[ [1 2] + [1 1 1]
[3 4]
[5 6]]
ลองเขียนโปรแกรมต่อไปนี้
ตัวอย่างโจทย์ระดับง่าย
โจทย์อาเรย์ 1 มิติ
1. คำนวณผลรวมของเลขคี่ที่อยู่ในช่วง 1-n โดยรับค่า n จากผู้ใช้
2. คำนวณค่าเฉลี่ยของคะแนนสอบของนักเรียน โดยรับคะแนนของนักเรียน n คน จากผู้ใช้
คำแนะนำ:
รับค่าเก็บไว้ในลิสต์
สร้างอาเรย์จากลิสต์
เรียกใช้ฟังก์ชัน mean ของอาเรย์
3. วิเคราะห์ข้อมูลหุ้น รับข้อมูลเกี่ยวกับราคาหุ้น n ตัวในช่วงเวลาหนึ่ง และวิเคราะห์ข้อมูลเหล่านี้เพื่อหาค่าสถิติที่ต่าง ๆ ได้แก่
ค่าเฉลี่ยราคาหุ้นในช่วงเวลานี้ (mean)
ค่าเบี่ยงเบนมาตรฐานของราคาหุ้น (std)
ราคาหุ้นที่มีมูลค่ามากที่สุด และน้อยที่สุด
ราคาหุ้นที่มีมูลค่าที่มากกว่าค่า x ที่สนใจ โดยรับค่า x จากผู้ใช้
ราคาหุ้นที่มีมูลค่าอยู่ในช่วง low - high โดยรับค่า low และ high จากผู้ใช้
หุ้นใดบ้างที่มีราคาหุ้นต่ำกว่าค่าเฉลี่ย (ระบุเป็นจริงหรือเท็จ)
5. เขียนโปรแกรมคำนวณหาค่า Mean Square Error (MSE)
# calculate mean square error
predictions = np.array([[1],[1],[1]])
labels = np.array([[1],[2],[3]])
print(labels.shape)
n = labels.shape[0]
error = prediction - labels
print(error)
square_error = .....
print(square_error)
mse = ....
print("%.2f" % mse) # 1.67
โจทย์อาเรย์ 2 มิติ
5. SumbyRowCol บนเกรดเดอร์
6. MatrixZone บนเกรดเดอร์
ตัวอย่างโจทย์ประยุกต์ ระดับปานกลาง
โจทย์อาเรย์ 1 มิติ
ExcludeMinus
Binary2Decimal
FactorNumber
TeamCompetition
โจทย์อาเรย์ 2 มิติ
6. ArrayUpDown บนเกรดเดอร์
7. MatrixSymmatric บนเกรดเดอร์
8.เขียนโปรแกรมคำนวณเกี่ยวกับยอดขายของพาย 3 ชนิด มีราคาดังนี้
Apple pies ราคาชิ้นละ $3
Cherry pies ราคาชิ้นละ $4
Blueberry pies ราคาชิ้นละ $2
จงหาเขียนโปรแกรมคำนวณค่าต่อไปนี้
ยอดขายในแต่ละวัน
ยอดขายรวมทุกวัน
ยอดขายพายแต่ละชนิด
รายรับของพายแต่ละชนิดรวมทุกวัน
รายรับของแต่ละวัน
รายรับรวมทั้งหมด
ศึกษาเพิ่มเติมได้ที่
วิดีโอ เริ่มเรียนเขียนโปรแกรม Python ๑๐๑ ภาควิชาวิศวกรรมคอมพิวเตอร์ จุฬาลงกรณ์มหาวิทยาลัย เลือกหัวข้อ 11. Numpy