ㅅㅇ

numpy _ 02_1 배열의 원소 조회 본문

AI_STUDY/Numpy

numpy _ 02_1 배열의 원소 조회

SO__OS 2022. 6. 24. 00:11
플레이데이터 빅데이터캠프 공부 내용 _ 6/22

numpy _ 02_1 배열의 원소 조회

배열의 원소 조회 : 인덱싱, 슬라이싱, 펜시, 부울 인덱싱, np.where ...

1. 배열 인덱싱(Indexing)

- index
    - 배열내의 원소의 식별번호
    - 0부터 시작 


- indexing 
    – index를 이용해 원소 조회
    - [] 표기법 사용

 

 

1) 1차원 배열 : axis(축)이 한 개 - > 지정할 수 있는 index도 1개

        - (10, )  : 0 축  0 ~ 9   조회 가능 - >  arr[ 0 ]

 

2) 다차원 배열 : axis(축)이 n 개 - > 지정할 수 있는 index도 1개

      - arr[0축 index, 1축 index, ..., n축 index]

 

        - (10,5)        # 0축 : 0~9,  1축 : 0~4  조회 가능

        - (3,4,5)       # 0축 : 0~2,  1축 : 0~3,   2축: 0~4  조회 가능

 

    shape 가 중요한 이유. shape 조회 결과를 이해하면 원소 조회 또한 쉽다.

 

  - 2차원배열의 경우 : axis(축)이 2 개 - > 지정할 수 있는 index도 2개

       - 0축 axis = 행 indix     1축 axis = 열 index

       - arr[행index, 열index]    a2[0,3]
          - 파이썬 리스트와 차이점 (list[행][열])

 

- 구문 
    - ndarray[index]
    - 양수는 지정한 index의 값을 조회한다. 
    - 음수는 뒤부터 조회한다. 
        - 마지막 index가 -1


- 팬시(fancy) 인덱싱
    - 여러개의 원소를 한번에 조회할 경우 리스트에 담아 전달한다.


    - 다차원 배열의 경우 각 축별로 list 로 지정


    - arr[[1,2,3,4,5]]
        - 1차원 배열(vector): 1,2,3,4,5 번 index의 원소들 한번에 조회


    - arr[[0,3],  [ 1,4]]
        - [0,3] - 0번축 index list,       [1,4] - 1번축 index list
             - - >  2차원 배열(matrix): [0,1], [3,4] 의 원소들 조회

        인덱싱[  ]  대괄호에서   [  0번축index , 1번축 index   ] 

        축 별은 콤마로 구분 짓는 것을 이해한다면,

        다차원 배열의 경우 각 축별로 list를 지정 하는 것을 이해할 수 있을 것이다.

 

 

1) 1차원 배열 (10,  ) _ 기본 조회 원소 하나 조회

a1 = np.arange(10)

# 인덱스 조회
a1[0], a1[4]

# 양수 index 음수 index
print(a1[[-1,9,-2,8]])

 

2) 1차원 배열 _ 팬시 인덱싱. 여러 개의 원소 조회

# 여러개(3,6,7)-fancy indexing
# 리스트로 묶어 0번축 내 여러 개의 원소를 
a1[[3,6,7]]

 

3) 1차원 배열 _ 원소 값 변경 

# 원소 값 변경
a1[0] = 100

# 여러 index의 값을 한번에 같은 값으로 변경
a1[[0,1,2]] = 1000

# 여러 index의 값을 한번에 각각의 값으로 변경
a1[[3,4,5]] = [700,800,900]

 

 

다차원(2차원 이상) 배열 조회
     [ , , , ]    '콤마'  를 기준으로 각 축 별로 index 를 지정

 

 

4) 2차원 배열 조회

-  shape (5, 6) 배열 생성 :   2차원 배열  a2[0축 index, 1축의 index]

a2 = np.arange(30).reshape(5,6)
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29]])

 

- 0번 축 조회

# 0번 축 :0
a2[0]
array([0, 1, 2, 3, 4, 5])

 

- 0번 축, 1번 축 조회
# 0번축 : 0   1번 축 :3
a2[0,3]
3

 

- fency : a2[ [0번축] ,[1번축] ] 조회

     -- > 같은 axis 끼리 리스트에 묶어서

     --  > 두 개의 축 사이에 같은 index에 맞춰 값이 반환됨.

 

a2[[2,3,4], [1,1,2]]
 
 
array([13, 19, 26])

 

 

5) 3차원 배열 조회

 

조회마다 결과로 나오는 배열의 shape를 이해하자.

 

 
a3 = np.arange(24).reshape(3,4,2)

# 0번 축의 1index
a3[1] # (4, 2) 2차원 배열 반환

# 0번 축의 2index, 1번 축의 1index
a3[2,1] # (2,) 1차원 배열 반환

#  0 축의 0 
# 1번축의 0, 1, 2  
# 2번축의 1, 1, 0   
a3[0, [0,1,2], [1, 1, 0]]

# (0, 0, 1)  (0, 1, 1)  (0, 2, 0) 

array([1, 3, 4])
 

2. 배열 슬라이싱slicing

- 배열의 부분 집합을 하위배열로 조회 및 변경하는 방식

- ndarry[start : stop : step ]

    - start : 시작 인덱스. 기본값 0
    - stop : 끝 index. stop은 포함하지 않는다. 기본값 마지막 index
    - step : 증감 간격. 기본값 1)
 
 

2.1  1차원 슬라이싱

a1 = np.arange(100)

# 3 ~ 9 조회
a1[3:10]

# 0 ~ 9 조회
a1[:10] 

# -5(마지막에서 5번째) ~ 마지막 조회
a1[-5:] # array([95, 96, 97, 98, 99])

# 5 ~ 74  step :5 조회
a1[5:75:5]

 

 

2.2  다차원 배열 슬라이싱

 

- 다차원의 경우
    - arr[0축 slicing , 1축 slicing , ... ,  n축 slicing]    -- >   콤마로 축을 구분한다. 

           - - > '각 축별 에 slicing 문법 적용   (slicing과 indexing, fancy 문법은 같이 쓸 수 있다. )

                   모든 축에 index를 지정할 필요는 없다.


- 2차원의 경우
    - arr [행 slicing , 열 slicing]
    - arr[        : 3      ,        :        ] 


          - - >   `,`  로 행과 열을 구분한 다중 슬라이싱 사용

 

 

1)  2차원 배열

 

- a2(0축, 1축)  :  축 별로. 인덱싱이든 슬라이싱이든 펜시이든

 

a2 = np.arange(30).reshape(5,6)
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29]])

 

2) 0번축 : 0 ~ 2 슬라이싱 조회  = >   행 3개,  열 전체 6개   (3, 6)

a2[:3]
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17]])

 

3) 0번축 : 1~3  슬라이싱 조회 = > 행 3개,  열 전체 6개   (3, 6)

a2[1:4]
array([[ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

 

4) 0번축 : 1~3   1번축 : 1~4   슬라이싱 조회   = > 행 3개,   열 4개    (3, 4)

a2[1:4, 1:5]
array([[ 7,  8,  9, 10],
       [13, 14, 15, 16],
       [19, 20, 21, 22]])

 

 

5)  0번 축 : 1 ~ 3 slicing 조회 , 1번 :  3 indexing  조회   = > 행 3개,   열 1개    (3,   )

a2[1:4, 3]
array([ 9, 15, 21])
 
 

6)  0번 축 : 1 ~ 3 slicing, 1번 : 2, 4, 5 fancy indexing  = > 행 3개,   열 3개    (3,  3)

a2[1:4, [2,4,5]]
array([[ 8, 10, 11],
       [14, 16, 17],
       [20, 22, 23]])

 

7) 3 차원 배열   

 

- 3차원 배열   (3,4,2 )

a3 = np.arange(24).reshape(3,4,2)
array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5],
        [ 6,  7]],

       [[ 8,  9],
        [10, 11],
        [12, 13],
        [14, 15]],

       [[16, 17],
        [18, 19],
        [20, 21],
        [22, 23]]])

 

- 0번 축 : 2 indexing,   1번 축 : 0 ~ 2 slicing   = >  (3,  2)

a3[2, :3]
array([[16, 17],
       [18, 19],
       [20, 21]])

 

- 0번 축 : 2 indexing,   1번 축 : 0 ~ 2 slicing,    2번 축 : 0, 1  fancy indexing     = >   (2, 3) 

 

★ 수평만 방향이라고 생각하지말고 수직으로도 값을 묶을 수 있는 방향이라고 생각하자.

 

-  2번축   0번 들고 오고,   1번 들고 오고    -- >    (2, 3)

a3[2, :3, [0,1]]
array([[16, 18, 20],
       [17, 19, 21]])

 

- 0번 축 : 2 indexing,   1번 축 : 0 ~ 2 slicing,    2번 축 : 1 indexing     = >   (3,  ) 

 

★ 수평만 방향이라고 생각하지말고 수직으로도 값을 묶을 수 있는 방향이라고 생각하자.

 

a3[2, :3, 1]
array([17, 19, 21])
 
 
 

2.3  슬라이싱은 원본에 대한 View 

- slicing한 결과는 새로운 배열을 생성하는 것이 아니라 기존 배열 원본을 참조한다.
     == >   slicing한 배열의 원소를 변경하면 원본 배열의 것도 바뀐다.

 
만약, 기존 배열을 바꾸고 싶지 않다면?

- 배열.copy()
    - 배열을 복사한 새로운 배열 생성
    - 복사후 처리하면 원본이 바뀌지 않는다.

 

 

1)   b는 a1 을 slicing  한 결과.

    -- >  슬라이싱하여 복사하면,원본을 참고한다. 

    -- >   b의 원소를 변경하면 a1의 원소도 같이 변경  :   (slicing : shallow copy)

 

a1 = np.arange(100)
b = a1[:10]
b[0] = 1000

# 원본도 바뀜.
a1[0]
1000
 
 

2) copy() 깊은 복사 (deep copy)  = >  원본이 안 바껴야 한다.

 

a1 = np.arange(100)
b2 = a1[:10].copy()
b2[0] = -300
a1[0]
0

 

3. boolean indexing

- Index 연산자에 Boolean 배열을 넣으면 True인 index의 값만 조회

                                                                (False가 있는 index는 조회하지 않는다.)


- 동일한 size 여야 한다.
ndarray내의 원소 중에서 원하는 조건의 값들만 조회할 때 사용

 

 

1)  numpy에서는 elements-wise 연산(원소단위 연산)을 지원

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

a > 5
a[a > 5]
array([False, False, False, False, False,  True,  True,  True,  True])
array([6, 7, 8, 9])

 

 

2)   and  : &      or : |       not :  ~
  파이썬 and, or, not 키워드 연산자는 사용안됨.  (넘파이, 판다스)
  피연산자는 ()로 묶어준다. (넘파이, 판다스)

 

a[(a<5) | (a>7)]

a[(a>5) & (a<9)]

a[~(a>5) & (a<9)]

 

 
 3) 다차원 배열 부울 인덱싱
 

 - 조건을 만족하는 값들이 1차원 배열로 나온다.
      == >  값을 알려주고,  구조가 똑같이 나오지 않는다. 나올 수가 없다.

b = np.arange(12).reshape(4,3)

b>5
b[b>5]
array([[False, False, False],
       [False, False, False],
       [ True,  True,  True],
       [ True,  True,  True]])
       
       
array([ 6,  7,  8,  9, 10, 11])

 

4. np.where()

- np.where(boolean 배열)  :  True인 index를 반환

   == > boolean연산과 같이쓰면, 특정 조건을 만족하는 원소의 index조회됨.

 

np.where(boolean 배열, True를 대체할 값, False를 대체할 값)
    - True와 False를 다른 값으로 변경한다.

- True의 index들을 ndarray로 묶어서 반환. 
    - 반환타입 : Tuple (축 별로 묶어서 반환)

 

 

1)   True인 index를 축 별로 배열ndarray로 나타내고   이는 튜플로 묶인다.

 

# 2차원 배열
np.where([[True, False],[True, False]])

 

     [0,1] : 0축의 index들  ,                [0,0] :1축의 index들   ===> (0,0) (1,0)    실제 값의 index는 같은 index끼리 묶어준다.

(array([0, 1], dtype=int64), array([0, 0], dtype=int64))

 

 

2) boolean indexing : 조건을 만족하는 값을 조회
    where() : 조건을 만족하는 값들의 위치(index)를 조회

 

b = np.arange(12).reshape(4,3)
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

 

np.where(b >5)
(array([2, 2, 2, 3, 3, 3], dtype=int64),   # 0축
 array([0, 1, 2, 0, 1, 2], dtype=int64))   # 1축

  = > (2,0)  (2,1)  (2,2)  (3,0)  (3,1)  (3,2)

 

 

3) 축 별 배열 결과를 인덱스로 받고 싶다면?

idx1, idx2 = np.where(b>5)

for o, t in zip(idx1, idx2):
    print(o,t, sep=',')

 

 

4) True, False를 다른 값으로 변경

a = np.arange(1,10)

np.where(a>5, '5이상', '5미만')
array(['5미만', '5미만', '5미만', '5미만', '5미만', '5이상', '5이상', '5이상', '5이상'],
      dtype='<U3')

 

 

5) value 자리에 배열 객체를 넣으면?

   비교한 조건의 값이 그대로 나온다.
      = > 타입을 맞춰줘서 모든 원소가 문자열로 나옴. 

 

( 넘파이 배열의 원소는 모두 동일한 데이터 타입이라는 규칙이 있다.

 True 인 애들이 문자열로 나오는데 이들은 같은 타입으로 통일할 때 가장 우선이기에

  결과는 a 배열 원소들이 문자열로 나온다. )

 

np.where(a>5, '5이상', a)

 

- 서로 다른 타입을 같은 타입으로 통일할 때 우선순위

논리형 < 정수 < 실수 < 문자열

 

5. 기타

- np.any(boolean 배열)
    - 배열에 True가 하나라도 있으면 True 반환
- np.all(boolean 배열)
    - 배열의 모든 원소가 True이면 True 반환

 

# 특정 조건을 만족하는 항이 하나라도 있는지 확인 -> any()
# 특정 조건을 배열의 모든 원소가 만족하는지 확인 -> all()
np.any(a > 5)
np.all(a > 5)

 

 

 

'AI_STUDY > Numpy' 카테고리의 다른 글

numpy _ 04_2 범용함수(Ufunc, Universal function)  (0) 2022.06.24
numpy _ 04_1 벡터 연산  (0) 2022.06.24
numpy _ 02_2 정렬  (0) 2022.06.24
numpy _ 01_2 배열 생성  (0) 2022.06.23
numpy _ 01_1 개요  (0) 2022.06.21