TOP
class="layout-aside-left paging-number">
본문 바로가기
[파이썬 Projects]/<파이썬 기초>

[파이썬] 넘파이 보완 - 불리언 값, 배열 전치 , 내적

by 기록자_Recordian 2025. 1. 24.
728x90
반응형
이전 내용
 

[파이썬] 넘파이(NumPy) - 1

시작에 앞서해당 내용은 ' 권철민 지음. 위키북스' 를 토대로 작성되었습니다. 보다 자세한 내용은 해당 서적을 참고해 주시기 바랍니다.  네이버 도서책으로 만나는 새로운 세상search.shopping.nav

puppy-foot-it.tistory.com


불리언 값으로 선택하기

 

아래와 같은 names 배열과 data 배열이 있다.

names = np.array(["Bob", "Joe", "Will", "Bob", "Will", "Joe", "Joe"])
data = np.array([[4,7],[0,2],[-5,6],[0,0],[1,2],[-12,-4],[3,4]])

print(f"names: \n{names}, dtype: {names.dtype}")
print(f"data: \n{data}, dtype: {data.dtype}")

 

- 이름에 Bob이 있는지 여부를 출력하면 아래와 같이 불리언 타입(True 또는 False)으로 값을 반환한다.

names == "Bob"

 

- 만약, names 배열과 data 배열의 수가 같다면 배열을 서로 대입해서 출력할 수 있다.

print(f"data 배열 중 Bob의 위치: \n{data[names == "Bob"]}")

이 의미는 data 배열의 값 행의 값을 names와 대입하고, 그 중 Bob 행과 같은 위치의 행을 출력하겠다는 뜻이다.

 

위 이미지를 통해 보면 Bob은 data 배열의 0번행, 3번행 이렇게 두 행과 일치하므로, 출력값으로 data 배열의 해당 행에 있는 값이 출력되는 것이다. (불리언 배열은 반드시 색인하려는 축의 길이와 길이가 동일해야 한다.)

 

- 그리고 뒤에 숫자를 붙여주게 되면 범위를 지정하거나, 단일 열을 선택할 수도 있다.

print(f"차원 그대로:\n {data[names == "Bob", 1:]}")
print(f"벡터로: {data[names == "Bob", 1]}")

  • 범위 지정: data[names == "Bob", 1:]는 names 열에서 "Bob"에 해당하는 행의 2번째 열부터 마지막 열까지를 선택한다. 이는 데이터프레임의 행을 선택하고, 해당 행의 특정 열 범위를 지정하는 방법이다.
  • 단일 열 선택: data[names == "Bob", 1]는 names 열에서 "Bob"에 해당하는 행의 2번째 열을 선택합니다. 이는 데이터프레임의 행을 선택하고, 해당 행의 단일 열을 지정하는 방법

◆ 여기서도 파이썬과 마찬가지로 != (같지 않음), ~(반대)를 사용할 수 있다.

print(f"names이 Bob이 아닌 배열: {names != "Bob"}")
print(f"names이 Bob이 아닌 배열: {~(names == "Bob")}")
print(data[~(names == "Bob")])

 

특히 ~ 연산자는 변수가 참조하는 불리언 배열을 뒤집고 싶을 때 유용하다.

cond = names == "Bob"
print(f"names가 Bob인 행렬: {cond}")
print(f"data 행렬 중 names가 Bob이 아닌 행렬:\n {data[~cond]}")

 

◆ 논리연산자(&: and, |:or)도 사용할 수 있다.

mask = (names == "Bob") | (names == "Joe")
print(f"이름이 Bob 이거나, Joe 인 배열: {mask}")

※ 단, 파이썬과는 다르게 파이썬 예약어인 and 나 or 를 사용하지는 못한다.

 

◆ 불리언 배열에 값 대입하기

print(data)
data[data < 0 ] = 0
print(data)

▶ 해당 코드로 인해 data 배열 중 모든 음수가 0으로 바뀐 것을 확인할 수 있다.

 

print(data)
data[names != "Joe"] = 7
data

names 중 Joe가 아닌 data 배열에 7 대입


팬시 색인

 

★ 팬시 색인(fancy indexing): 정수 배열을 사용한 색인을 설명하기 위해 넘파이에서 차용한 단어로, 리스트나 ndarray로 인덱스 집합을 지정하면 해당 위치의 인덱스에 해당하는 ndarray를 반환한다.

 

0으로 만든 8*4 배열에 for 반복문을 이용하여 각 행에 0부터 7까지 행으로 채운다.

arr = np.zeros((8,4))
print(arr)

for i in range(8):
    arr[i] = i
arr

 

이 중에서 4번, 3번, 0번, 6번 행을 출력해보면

arr[[4,3,0,6]]

위 코드는 아래 코드의 의미와 비슷하다.

print(arr[4])
print(arr[3])
print(arr[0])
print(arr[6])

 

파이썬처럼 -를 붙여주면 뒤부터 출력할 수 있다.

arr[[-3, -5, -7]]


배열 전치와 축 바꾸기

 

★ 배열 전치(transpose): 데이터를 복사하지 않고 데이터의 모양이 바뀐 뷰를 반환하는 특별한 기능

ndarray는 transpose 메서드와 T라는 이름의 특수한 속성을 가진다.

 

1부터 14까지 15개의 값을 가지는 3*5 크기의 배열을 만들고

arr3 = np.arange(15).reshape(3,-1)
arr3

 

전치 변환을 하게 되면

arr3.T

축이 바뀌게 된다. (가로 → 세로, 세로 가로)

 

◆ swapaxes

arr5 = np.array([[0,1,0],[1,2,-2],[6,3,2],[-1,0,-1],[1,0,1]])
arr5
arr5.swapaxes(0, 1) # 0(가로)과 1(세로)의 축을 바꿈

 

 

◆ dot: 행렬의 내적

1부터 6까지의 6개의 값을 가진 2*3 크기의 arr4 배열을 만들고,

이 배열을 전치 행렬하고

arr4 배열과 전치 행렬을 내적하면 아래와 같은 값이 출력된다.

arr4 = np.arange(1,7).reshape(2,-1)
print(arr4)
# 전치 행렬
print(arr4.T)
# 내적: 
print(np.dot(arr4.T, arr4))

내적을 구할 때는 numpy의 dot을 사용하는데, dot(전치행렬, 기존 배열)을 인자로 입력해주면 된다.

print(np.dot(arr4, arr4.T))

와는 값이 다르다.

 

앞의 코드 'print(np.dot(arr4.T, arr4))' 의 값이 구해지는 원리를 풀어보면,

 

각 배열끼리 곱해지고, 해당 곱셈의 값이 아래와 같은 9자리 배열에 대입된다.

1 2 3
4 5 6
7 8 9

 

  • 1번식: 1*1+4*4 = 27
  • 2번식: 1*2+4*5= 22
  • 3번식:  1*3+4*6 = 27
  • 4번식: 2*1+5*4 = 22
  • 5번식: 2*2+5*5 = 29
  • 6번식: 2*3 + 5*6 = 36
  • 7번식: 3*1+6*4 = 27
  • 8번식: 3*2+6*5 = 36
  • 9번식: 3*3+6*6 = 45

의 값이 나오게 된다.

 

 

 

 

 

728x90
반응형