본문 바로가기

Programming Language/Python_library

파이썬_응용단계 ep.3 배열 깎는 조각가

320x100
서론

 

 

16세기의 걸출한 조각가 미켈란젤로에게는

이러한 일화가 있습니다.

 

다비드상, 피에타상과 같은 걸출한 조각상을

믿기 힘들정도로 빨리 제작한 이후입니다.

 

 

누군가가 미켈란젤로에게 다비드상을 어떻게

이렇게 사람처럼 만들게 되었느냐고 물었을 때,

 

미켈란젤로는 제작 초기 거대한 석고 뭉치를 보면서

이렇게 생각했다고 하죠?

 

그 안에 이미 조각상이 서있었소

저는 망치와 끌로

그사람을 현실로 꺼내주었을 뿐이오

 

 


 

 

이미 그의 손 안에는 석고뭉치가 아닌

잘 깎인 조각상이 있었던 것 같습니다.

 

 

몇 가지 단순한 도구들을 통해 예술가는

딱딱한 덩어리들에서 경이로움을,

혹은 어떠한 숭고한 가치를 꺼내놓기도 합니다.

 

 

우리도 할 수 있습니다.

물론 대단하진 않지만, numpy에서 할 수 있습니다.

 

 

배열을 다루는 여러가지 망치와 끌도 있습니다.

바로 여러가지 특수문자와 메서드 들인데요.

 

앞서서, 인덱스와 슬라이스를 배워보겠습니다.

 


 

일차원 배열의 인덱싱(Indexing)

 

우리말로는 찾아보기

 

먼저 의문점이 있습니다

인덱싱이 왜 필요할까요?

 

 


 

아무래도 numpy에서 바로 사용하기 보다는

우리가 pandas를 통해 데이터를 조작하고 통제할때

더욱 유용하게 사용하기 위해서 쓰는 것입니다.

 

직접적으로는 전체 초등학생 성적에서 상위 10%의

성적만 보고싶은 경우나, 2022 월드컵에서 승점 하위 30%를 필요로 할때,

서울시 건강보험료 중위권 인구 등 통계 데이터에서 우리가

보고싶은 수치만 뽑아서 보고 싶을때 필요하기 때문입니다.

 

인덱싱과 슬라이싱 모두 마찬가지입니다.

 

일차원 배열은 리스트의 인덱싱과 동일합니다.

 

 

a = np.array([0,1,2,3,4])

#a >> 3을 가져오고 싶다.
a[2]
3

 

[]에 위치값을 불러오면, 값이 찍히게 됩니다.

 

a[2], a[-1]
(2, 4)

 

다시 보겠습니다.

 

b = np.arange(3,10)
b
array([3, 4, 5, 6, 7, 8, 9])

 

b의 1번,2번,3번째 입니다.

 

b[1], b[2], b[3]
(4, 5, 6)

 

어려울 것이 없습니다.

 

이번엔 2, 3차원 배열의 인덱싱을 보겠습니다.

 

다차원 배열 인덱싱

 

구조

 

콤마(comma , '  ,  ')로 구분합니다.

콤마로 구분된 차원을 축(axis)라고 합니다.

함수 그래프의 x축, y축과 같은 개념입니다.

 

이때 axis는 주기적으로 등장하므로

기억해 두는 것이 좋겠습니다⛄

 

다른 2차원 배열을 소환해보겠습니다.

 

b = np.array([
    [0,1,2],
    [3,4,5]
])
b
array([[0, 1, 2],
       [3, 4, 5]])

 

이러한 b의 행렬은 2행 3열 이라고 표현할 수 있겠죠?

 🔥 기본적으로 0행, 0열부터 순서가 시작됩니다!

 

b.shape
(2, 3)

 

b의 0번째 행의 0번째 열은요?

 

b[0,0]
0

 

b의 1번째 행(마지막 행)과 2번째 열(마지막 열)은요?

 

b[1,2]
5

 

b의 0번째 행의 1번째 열은요?

 

b[0,1]
1

 

자 이번에는 -1번째 행과 -1번째 열도 보겠습니다.

 

b[-1, -1]
5

 

마지막 행의 마지막 열이 됩니다.

좋습니다. 좀 더 어려운 인덱싱을 진행해 보겠습니다.

 

불리언 배열 인덱싱

 

어떠한 경우에 불리언 배열 인덱싱을 할까요?

 

인덱스 배열의 원소가 True, False 두 값으로만 구성되며

인덱스 배열의 크기가 원래 ndarray 객체의 크기와 같을때

진행합니다.

 

배열 소환

 

a = np.array([0,1,2,3,4,5,6,7,8,9])

 

여기서 0~9 사이의 짝수만 불러내고 싶다면 어떻게 해야 할까요?

 

idx = np.array([True, False, True, False, True, False, True, False, True, False])
a[idx]

 

이렇게 idx의 True, False 값를 갖고 칼질을 하듯이 인덱싱 해봅시다.

 

array([0, 2, 4, 6, 8])

 

좋습니다.

 

다른 방법도 있습니다.

짝수라는 것은 2로 나누었을 때, 나머지가 0인 숫자들을 의미합니다.

 

산술 연산으로 표현해 볼까요?

 

a% 2 == 0

그대로 반환합니다.

 

array([ True, False,  True, False,  True, False,  True, False,  True,
       False])

 

조건문으로 계산해서 (벡터화 연산) 원래 배열에 인덱스로 넣어주면,
필터링이 되는 것입니다.
 
a[a%2==0]
array([0, 2, 4, 6, 8])

 

이렇게 하면 3의 배수도 구할 수 있습니다.

 

a[a%3 ==0]
array([0, 3, 6, 9])

 

정수 배열 인덱싱

 

정수의 주소값들만 작성되어 있는 배열로

정수 배열 인덱싱도 가능합니다.

 

원래 배열의 인덱스로 정수값의 라벨링을 진행하는 것이죠

0부터 시작합니다.

 

a = np.array([1,2,3,4,5,6,7,8,9])
a
array([1, 2, 3, 4, 5, 6, 7, 8, 9])

 

정수 배열로 인덱싱

 

idx = np.array([0,2,4,6,8])
a[idx]
array([1, 3, 5, 7, 9])

 

특별하게도, 값을 반복하는 것도 가능합니다.

 

idx2 = np.array([0,0,0,0,1,1,1,1,2,2,2,2])
a[idx2]
array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3])

 

다음은 슬라이싱을 진행하겠습니다.

 

배열의 슬라이싱(Slicing)

 

슬라이싱, 이름에서 주는 날카롭고 날렵한 느낌과는 달리

콜론이라는 뭉툭한 재질의 문자를 사용합니다. 

구조   [ x : y ]

 

x = [1,2,3,4]
x[1:2]
[2]

 

1차원 배열은 쉽습니다. 앞쪽에는 시작하는 주소, 뒤쪽에는 끝나는 주소를

입력하면 끝입니다.

 

x[-4:4]
[1, 2, 3, 4]

 

2차원 이상의 배열에서는 어떻게 할까요?

일반적인 파이썬 슬라이싱과 콤마를 같이 사용합니다.

 

배열 소환

 

a = np.array([
      [0,1,2,3,4],
      [4,5,6,7,8]
      ])
a
array([[0, 1, 2, 3, 4],
       [4, 5, 6, 7, 8]])

 

0번째 행 전체

어떻게 할까요? 행은 지정해주고, 열은 : 만 남기고 비워줍니다.

 

a[0, :]
array([0, 1, 2, 3, 4])

 

0번째 열 전체

이번에는 반대로 행은 : 만 남기고 비우면서, 열을 지정해주면 좋겠죠?

 

a[:, 0]
array([0, 4])

 

1번째 행~2번째 행과 1번째 열~2번째 열까지

슬라이싱 하면 어떻게 될까요?

 

a[:2, :2]
array([[0, 1],
       [4, 5]])

 

좋습니다.

이는 아까전에 제시했던 불리언 배열에서도 가능합니다.

 

불리언 배열

 

[True, False,True, False,True]

 

위는 열입니다.

모든 행과 합쳐보겠습니다.

 

a[:,[True, False,True, False,True]]
array([[0, 2, 4],
       [4, 6, 8]])

 

이렇게 출력되게 됩니다.

이번에는 검색을 해보겠습니다.

 

배열 검색
구조

 

np.where ( )

그 인수가 위치하는 위치값을 반환합니다.

 

arr = np.array([1,2,3,4,5,4,4,])
arr
array([1, 2, 3, 4, 5, 4, 4])

 

배열을 만들었습니다. 

4의 위치값은 어디일까요?

 

x = np.where(arr == 4)
x
(array([3, 5, 6]),)

 

자, 3번째, 5번째, 6번째로 반환됩니다.

 

이번엔 1부터 8까지의 짝수를 반환해볼까요?

 

arr = np.array([1,2,3,4,5,6,7,8])
x = np.where(arr%2 ==0)

arr[x]
array([2, 4, 6, 8])

 

x
(array([1, 3, 5, 7]),)

 

좋습니다.

x는 1번째, 3번째, 5번째, 7번째에 위치값을 갖는다는 점을

알 수 있습니다.

 

다음시간에는 배열의 갖가지 자료형과 생성+변형을 확인해보겠습니다!

이 시리즈는 numpy를 마스터하는 그날까지 계속됩니다✨✨✨

728x90