In deze notebook leer je de meest gebruikte NumPy-operaties voor data-analyse:
Element-gewijze versus matrix-bewerkingen
Broadcasting โ operaties op arrays van verschillende groottes
Aggregaties langs assen
Hervorming en samenvoegen van arrays
โ ๏ธ Het verschil tussen * (element-gewijs) en @ (matrixvermenigvuldiging) is de meest voorkomende verwarring โ we behandelen het expliciet.
import numpy as npElement-gewijze operatiesยถ
Alle standaard rekenkundige operatoren (+, -, *, /, **) werken element-gewijs op arrays van dezelfde vorm.
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
print(a + b) # [ 11 22 33 44]
print(a * b) # [ 10 40 90 160]
print(b / a) # [10. 10. 10. 10.]
print(a**2) # [ 1 4 9 16][11 22 33 44]
[ 10 40 90 160]
[10. 10. 10. 10.]
[ 1 4 9 16]
# Mathematical functions also work element-wise
angles = np.linspace(0, np.pi, 5)
print(np.sin(angles).round(4))
print(np.exp(np.array([0, 1, 2])))[0. 0.7071 1. 0.7071 0. ]
[1. 2.71828183 7.3890561 ]
โ ๏ธ * vs. @ โ element-gewijs vs. matrixvermenigvuldigingยถ
Dit is de meest voorkomende verwarring bij NumPy:
*โ element-gewijze vermenigvuldiging (Hadamard product)@โ matrixvermenigvuldiging (dot product)
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print("A * B (element-wise):")
print(A * B)
print()
print("A @ B (matrix multiplication):")
print(A @ B)A * B (element-wise):
[[ 5 12]
[21 32]]
A @ B (matrix multiplication):
[[19 22]
[43 50]]
# Dot product of two vectors
x = np.array([1, 2, 3])
w = np.array([0.5, 0.3, 0.2]) # weights
print("dot product:", x @ w) # 1*0.5 + 2*0.3 + 3*0.2 = 1.7
print("element-wise:", x * w) # [0.5 0.6 0.6] โ three separate valuesdot product: 1.7000000000000002
element-wise: [0.5 0.6 0.6]
Broadcastingยถ
Broadcasting laat NumPy toe om operaties uit te voeren op arrays van verschillende vormen, door de kleinere array automatisch uit te breiden. Dit vermijdt onnodige geheugenkopieรซn.
Regel: Dimensies zijn compatibel als ze gelijk zijn, of als รฉรฉn van beide 1 is.
# Scalar + array: the scalar is broadcast to every element
a = np.array([1, 2, 3, 4])
print(a + 10) # [11 12 13 14]
print(a * 2) # [ 2 4 6 8][11 12 13 14]
[2 4 6 8]
# Row vector + matrix: the row is broadcast to every row of the matrix
M = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
row = np.array([10, 20, 30]) # shape (3,)
print(M + row)
# M[0] + row, M[1] + row, M[2] + row[[11 22 33]
[14 25 36]
[17 28 39]]
# Practical example: row normalization via broadcasting
# Scale each row of M so the maximum per row equals 1
row_maxima = M.max(axis=1, keepdims=True) # shape (3, 1)
normalized = M / row_maxima
print(normalized.round(2))[[0.33 0.67 1. ]
[0.67 0.83 1. ]
[0.78 0.89 1. ]]
Aggregaties langs assenยถ
Aggregatiefuncties kunnen langs een bepaalde as (axis) werken:
axis=0: langs de rijen (per kolom)axis=1: langs de kolommen (per rij)
# Dataset: 4 students, 3 scores each
scores = np.array([[85, 90, 78], [72, 68, 80], [95, 92, 88], [60, 74, 70]])
print("Mean per student (per row):", scores.mean(axis=1))
print("Mean per test (per column): ", scores.mean(axis=0))
print("Overall mean: ", scores.mean())Mean per student (per row): [84.33333333 73.33333333 91.66666667 68. ]
Mean per test (per column): [78. 81. 79.]
Overall mean: 79.33333333333333
print("Max per student:", scores.max(axis=1))
print("Min per test: ", scores.min(axis=0))
print("Sum per student:", scores.sum(axis=1))Max per student: [90 80 95 74]
Min per test: [60 68 70]
Sum per student: [253 220 275 204]
Hervorming (reshape)ยถ
Met reshape verander je de vorm van een array zonder de data te wijzigen. Het totale aantal elementen moet gelijk blijven. De notatie -1 laat NumPy de ontbrekende dimensie automatisch berekenen.
a = np.arange(12)
print("1D:", a)
print("\n3ร4 matrix:")
print(a.reshape(3, 4))
print("\n2ร6 matrix:")
print(a.reshape(2, -1)) # -1: NumPy computes 12/2 = 61D: [ 0 1 2 3 4 5 6 7 8 9 10 11]
3ร4 matrix:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
2ร6 matrix:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
# flatten() always returns a 1D copy
M = np.array([[1, 2, 3], [4, 5, 6]])
print(M.flatten())
# Transpose
print(M.T) # or np.transpose(M)[1 2 3 4 5 6]
[[1 4]
[2 5]
[3 6]]
Arrays samenvoegenยถ
Met np.vstack, np.hstack en np.concatenate voeg je arrays samen.
A = np.array([[1, 2, 3], [4, 5, 6]])
B = np.array([[7, 8, 9]])
# vstack: stack vertically (add new rows)
print(np.vstack([A, B]))[[1 2 3]
[4 5 6]
[7 8 9]]
C = np.array([[10], [11]])
# hstack: stack horizontally (add new columns)
print(np.hstack([A, C]))[[ 1 2 3 10]
[ 4 5 6 11]]
# Sorting
data = np.array([3, 1, 4, 1, 5, 9, 2, 6])
print(np.sort(data)) # sorted copy
print(np.argsort(data)) # indices that would sort the array[1 1 2 3 4 5 6 9]
[1 3 6 0 2 4 7 5]
Oefeningenยถ
Oefening 1 โ Gegeven x = np.array([2, 4, 6, 8]) en y = np.array([1, 3, 5, 7]):
Bereken de element-gewijze vermenigvuldiging
Bereken het dot product
Leg in een comment het verschil uit
x = np.array([2, 4, 6, 8])
y = np.array([1, 3, 5, 7])
# your solution hereOefening 2 โ Gegeven de matrix M = np.random.default_rng(0).integers(1, 100, (5, 4)) (5 studenten, 4 testen):
Bereken het gemiddelde per student (per rij)
Bereken de standaardafwijking per test (per kolom)
Druk de naam af van de โbesteโ student (hoogste gemiddelde) โ gebruik
np.argmax()
names = ["Alice", "Bob", "Charlie", "Diana", "Eve"]
M = np.random.default_rng(0).integers(1, 100, (5, 4))
print(M)
# your solution here[[85 64 51 27]
[31 5 8 2]
[18 81 65 91]
[50 61 97 73]
[63 54 56 93]]
Oefening 3 โ Broadcasting oefening: Gegeven een matrix prices (3 producten ร 4 kwartalen) en een array vat_rates (รฉรฉn per product). Bereken de prijzen inclusief BTW via broadcasting zonder een for-lus.
prices = np.array([[100, 110, 105, 115], # product A
[200, 210, 195, 220], # product B
[ 50, 52, 48, 55]]) # product C
vat_rates = np.array([0.06, 0.21, 0.06]) # VAT rate per productprices = np.array([[100, 110, 105, 115], [200, 210, 195, 220], [50, 52, 48, 55]])
vat_rates = np.array([0.06, 0.21, 0.06])
# your solution here โ tip: vat_rates must have shape (3,1) for broadcastingOefening 4 โ Hervorming en samenvoegen:
Maak een array
a = np.arange(24)en hervorm hem naar een 4ร6-matrixSplits de matrix in een linker helft (eerste 3 kolommen) en een rechter helft (laatste 3 kolommen)
Stapel de twee helften verticaal met
np.vstack
# your solution here