ㅅㅇ
numpy _ 02_1 배열의 원소 조회 본문
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번축 : 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한 배열의 원소를 변경하면 원본 배열의 것도 바뀐다.
- 배열.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)]
- 조건을 만족하는 값들이 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 |