3.3 배열의 연산
1. 백터화 연산
- 앞서 넘파이가 백터화 연산을 지원한다고 이야기 함.
- 백터화 연산을 쓰면 명시적으로 반복문을 사용하지 않아도 배열의 모든 원소에 대해 반복연산이 가능
- 백터화 연산의 또다른 장점은 선형 대수 공식과 동일한 아주 간단한 파이썬 코드를 작성할 수 있음.
- 예를 들어 선형 대해수에서 두 벡터의 합은 다음과 같이 구함.
- (그림 참고)
- 만약 백터화 연산을 사용하지 않으면 반복문을 사용하여 다음과 같이 만들어야 한다.
- 이 코드에서 %%time은 셀 코드 실행시간 측정하는 아이파이썬 매직 명령이다.
x = np.arange(1, 10001)
y = np.arange(10001, 20001)
%%time
z = np.zeros_like(x)
for i in range(10000):
z[i] = x[i] + y[i]
#결과
Wall time: 4 ms
z[:10]
#결과
array([10002, 10004, 10006, 10008, 10010, 10012, 10014, 10016, 10018,
10020])
- 그러나 백터화 연산을 사용하면 덧셈 연산 하나로 끝!
%%time
z = x + y
#결과
Wall time: 989 µs
z[:10]
#결과
array([10002, 10004, 10006, 10008, 10010, 10012, 10014, 10016, 10018,
10020])
# 사칙 연산뿐만이 아니라 비교 연산도 백터화 연산이 가능
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
a == b
#결과
array([False, False, False, False])
a >= b
#결과
array([False, False, False, False])
# 모든 원소 다 같이 비교는 all 명령어
a = np.array([1, 2, 3, 4])
b = np.array([4, 2, 2, 4])
c = np.array([1, 2, 3, 4])
np.all(a == b)
False
#결과
np.all(a == c)
#결과
True
# 지수 함수, 로그 함수 등의 수학 함수도
# 백터화 연산을 지원한다.
a = np.arange(5)
a
#결과
array([0, 1, 2, 3, 4])
np.exp(a)
#결과
array([ 1. , 2.71828183, 7.3890561 , 20.08553692, 54.59815003])
10 ** a
#결과
array([ 1, 10, 100, 1000, 10000], dtype=int32)
np.log(a + 1)
#결과
array([0. , 0.69314718, 1.09861229, 1.38629436, 1.60943791])
2. 스칼라와 벡터/행렬의 곱셈
- 스칼라와 벡터/행렬의 곱도 선형 대수에서 사용하는 식과 넘파이 코드가 일치
x = np.arange(10)
x
#결과
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
x = np.arange(12).reshape(3, 4)
x
#결과
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
100 * x
#결과
array([[ 0, 100, 200, 300],
[ 400, 500, 600, 700],
[ 800, 900, 1000, 1100]])
3. 브로드캐스팅
- 백터(또는 행렬)끼리 덧셈 등을 하려면 크기가 같아야 함.
- 넘파이엥서는 서로 다른 크기 가진 두 배열의 사칙 연산도 지원.
- 이 기능을 브로드캐스팅(brodcasting)
x = np.arange(5)
x
#결과
array([0, 1, 2, 3, 4])
y = np.ones_like(x)
y
#결과
array([1, 1, 1, 1, 1])
x + y
#결과
array([1, 2, 3, 4, 5])
x + 1
#결과
array([1, 2, 3, 4, 5])
# 😂
x = np.vstack([range(7)[i:i + 3] for i in range(5)])
x
#결과
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])
# 😂
y = np.arange(5)[:, np.newaxis]
y
#결과
array([[0],
[1],
[2],
[3],
[4]])
x + y
#결과
array([[ 0, 1, 2],
[ 2, 3, 4],
[ 4, 5, 6],
[ 6, 7, 8],
[ 8, 9, 10]])
4. 차원 축소 연산
- 넘파이는 다음과 같은 차원 축소 연산 명령 혹은 메서드를 지원한다.
- 최대/최소 : min, max, argmin, argmax
- 통계 : sum, mean, median, std, var
- 불리언 : all, any
x = np.array([1, 2, 3, 4])
x
#결과
array([1, 2, 3, 4])
np.sum(x)
#결과
10
x = np.array([1, 3, 2])
x.min()
#결과
1
x.max()
#결과
3
x.argmin() #최솟값의 위치
#결과
0
x.argmax() #최솟값의 위치
#결과
1
x = np.array([1, 2, 3, 1])
x.mean()
#결과
1.75
np.median(x)
#결과
1.5
np.all([True,True, False])
#결과
False
np.any([True, True, False])
#결과
True
a = np.zeros((100, 100), dtype=np.int)
a
#결과
array([[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
...,
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0]])
np.all(a == a)
#결과
True
np.any(a != 0)
#결과
False
a = np.array([1, 2, 3, 2])
b = np.array([2, 2, 3, 2])
c = np.array([6, 4, 4, 5])
((a <= b) & (b <= c)).all()
#결과
True
- 연산의 대상이 2차원 이상인 경우에는 어느 차원으로 계싼을 할 지를 axis 인수를 사용하여 지시
- axis=0인 경우는 열 연산. 디폴트 값은 axis=0
- axis=1인 경우는 행 연산.
x = np.array([[1, 1], [2,2]])
x
#결과
array([[1, 1],
[2, 2]])
x.sum()
#결과
6
x.sum(axis=0) # 열 합계
#결과
array([3, 3])
x.sum(axis=1) # 행 합계
#결과
array([2, 4])
5. 정렬
- sort함수나 메서드를 사용하여 배열 안의 원소를 크기에 따라 정렬하여 새로운 배열을 만들 수 있다.
- 2차원 이상인 경우 axis인수를 사용
- 디폴트 값은 -1 즉 가장 안쪽(나중)의 차원이다.
a = np.array([[4, 3, 5, 7],
[1, 12, 11, 9],
[2, 15, 1, 14]])
a
#결과
array([[ 4, 3, 5, 7],
[ 1, 12, 11, 9],
[ 2, 15, 1, 14]])
np.sort(a) # axis=-1 또는 axis=1 과 동일
#결과
array([[ 3, 4, 5, 7],
[ 1, 9, 11, 12],
[ 1, 2, 14, 15]])
np.sort(a, axis=0)
#결과
array([[ 1, 3, 1, 7],
[ 2, 12, 5, 9],
[ 4, 15, 11, 14]])
# sort메서드는 해당 객체의 자료 자체가
# 변화하는 자체변화(in-place) 메서드이므로 사용할 때 주의
a.sort(axis=1)
a
#결과
array([[ 3, 4, 5, 7],
[ 1, 9, 11, 12],
[ 1, 2, 14, 15]])
# 만약 자료를 정렬하는 것이 아니라
# 순서만 알고 싶다면? argsort 사용
a = np.array([42, 38, 12, 25])
j = np.argsort(a)
j
#결과
array([2, 3, 1, 0], dtype=int64)
a[j]
#결과
array([12, 25, 38, 42])
np.sort(a)
#결과
array([12, 25, 38, 42])
'😀 기초 > 넘파이(NumPy)' 카테고리의 다른 글
3장 난수 발생과 카운팅(3.5) (0) | 2022.01.25 |
---|---|
3장 넘파이 배열의 생성과 변형(3.2) (0) | 2022.01.25 |
3장 넘파이 배열 프로그래밍(3.1) (0) | 2022.01.24 |
NumPy 한번에 끝내기 (0) | 2022.01.18 |