NAN/Python

[NumPy_1] 소개 / 배열 만들기 / 원소 다루기

onddd 2021. 6. 29. 14:00
728x90

 

소개


 

 

이제까지 파이썬 기초 문법에 대해 공부했다면, 데이터를 효과적으로 다룰 수 있는 라이브러리에 대해 공부해보자

 

파이썬을 효율적인 언어로 부상시킨 요인은 객체 지향적인 문법으로 인한 낮은 진입 장벽과 데이터를 효율적으로

 

사용할 수 있게 만든 라이브러리의 역할이 컸는데 그 라이브러리가 'NumPy'이다. 

 

파이썬은 c언어에 비해 느린 속도로 인해 사용이 많지 않았으나 NumPy가 c언어를 기반으로 만들어져 아쉬웠던

 

속도가 빨라져 자연스럽게 많은 사용자의 선호를 얻게 되었다. 

 

NumPy 이는 ndarray 객체를 통해 1차원이 아닌 n차열 배열이 사용 가능한데, 언뜻 보기에 파이썬의 list와 비슷하지만,

 

동적 할당인 list와 다르게 정적 할당이라는 점에서 가장 큰 차이를 갖는다. (튜플과 비슷한 성질을 갖는다.)

 

앞에서 넘파이는 n차원 배열을 갖는다 했는데 2차원 이상을 표현하는 방법은 다음과 같다.

 

 

[[0,0,0],
 [1,1,1]]
 
 0번째 축의 길이는 2이고 1번째 축의 길이는 3으로 할당되어있는 2차원 배열이다.

 

[[[0,0,0],
  [1,1,1]],
 
 [[2,2,2],
  [3,3,3]],
  
 [[4,4,4],
  [5,5,5]],
   
 [[6,6,6],
  [7,7,7]]]
  
  0번째는 4, 1번째는 2, 3번째는 3의 축을 갖는 3차원 배열이다.

 

 

각 축을 제대로 구분하는 건 앞으로도 아주  중요하기 때문에 눈에 잘 담아두도록 하자.

 

 

 

 

 

 

다차원으로 갈수록 축이 많아지고 축을 구성하는 데이터 요소들 또 한 많아지기 때문에

 

행렬에 대한 기초 개념이 헷갈리는 일은 없어야 한다. 위 테이블 박스를 기준으로 세로를 행, 가로를 열이라고 한다.

 

2차원 데이터의 axis = 0 은 행 axis = 1은 열인 셈이다. 3차원으로 넘어가게 되면 그때부턴 채널, 혹은 텐서라고 부른다.

 

NumPy 이는 외부 라이브러리이기 때문에 이를 사용하기 위해선 데이터를 불러와야 하는데 설치되어있다면. 

 

import numpy를 통해 사용 선언을 해주는데, 이렇게 선언하면 사용할 때마다 numpy. 을 붙여야 하기 때문에

 

사용의 편의상 import numpy as np를 적용하여 np라는 별칭을 붙여 사용하는 게 보통이다.

 

 


 

Numpy 배열 만들기

 

 

넘 파이를 사용해 배열을 만드는 방법은 비교적 간단하다, 기존 파이썬에서 사용하던 list와 tuple 타입의 자료형에서

 

np.array를 붙여주면 몇 차원이든 원하는 데로 만들 수 있다.

 

import numpy as np

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

[1,2,3]

 

배열을 만들었으면 항상 사용하기 쉽게 변수에 할당하여 사용하자, 

 

그대로 사용할 수도 있지만 코드가 쌓여있는 상태가 된다면 어떤 코드인지 확인하기가 쉽지 않기 때문에

 

처음부터 습관을 들여야 한다.

 

넘 파이를 통해 배열을 생성한다면 같은 타입의 자료형밖에 올 수 없기 때문에 만약 int와 float이 섞여 있는 상태의

 

자료형을 array이 한다면 자동으로 전체 타입을 통일시켜준다.

 

 

arr2 = ([(1.5, 2, 3), (4, 5, 6)])

print(arr2)

[[1.5 2. 3.],
 [4. 5. 6.]]
 

 

 

int와 float이 섞여있는 튜플 타입의 자료형을 array이 하니, 자료 전체가 실수로 전환되어 출력되었다.

 

타입을 자동으로 전환해준다는 건 실수가 줄어들 수 있어 좋은 기능이긴 하지만,

 

추후에 전환된 자료 타입으로 인해 혼란이 올 수 있으니 항상 dtype을 통해 타입을 지정하자

 

 

arr3 = np.array([1,1], dtype=np.float64)

print(type(arr3))

print(arr3)

<class 'numpy.ndarray'>
[1. 1.]

float뿐만아니라 int, str 모두 사용 가능하다.

 

기본적으로 생성되는 array의 기본 값은 float64이다.

 

수집한 데이터를 시각화할 때에는 바로 실현 데이터를 넣기보다 0, 1 또는 무작위 수를 넣어놓고 설계를 마무리한 후

 

실현 데이터로 수정하는 경우가 잦은데, 이때 사용하게 되는 함수로는 np.zeros(), np.ones(), np.empty()등이 있다.

 

 

arr = np.zeros([2,2], dtype=np.int64)
arr2 = np.ones([3,2,2], dtype=np.int64)
arr3 = np.empty([3,3,2,1], dtype=np.int64)

print(arr)
print()
print(arr2)
print()
print(arr3)

[[0 0]
 [0 0]]

[[[1 1]
  [1 1]]

 [[1 1]
  [1 1]]

 [[1 1]
  [1 1]]]

[[[[4607182418800017408]
   [4607182418800017408]]

  [[4607182418800017408]
   [4607182418800017408]]

  [[4607182418800017408]
   [4607182418800017408]]]


 [[[4607182418800017408]
   [4607182418800017408]]

  [[4607182418800017408]
   [4607182418800017408]]

  [[4607182418800017408]
   [4607182418800017408]]]


 [[[4607182418800017408]
   [4607182418800017408]]

  [[4607182418800017408]
   [4607182418800017408]]

  [[4607182418800017408]
   [4607182418800017408]]]]

 

각 함수를 통해 2,3,4, 차원을 임의 데이터로 만든 모습이다. 

 

 


 

np.arrange()와 np.linspace()

 

 

파이썬에서 range() 함수를 사용하면 지정한 숫자 n-1까지의 숫자를 출력받을 수 있었는데,

 

numpy 역시 그와 같은, 비슷한 기능을 가지고 있다.

 

먼저 np.arrange()는 주어진 범위에서 균일한 간격의 값을 갖는 배열(array)을 생성했는데

 

np.linspace()의 경우 이와 흡사하지만 미묘한 차이를 가지고 있다.

 

바로 지정된 스탭이 아닌 지정된 개수에 맞게 값을 균등하게 나눈다는 것이다.

 

 

arr = np.arange(0,10,2,dtype=np.int64)

print(arr)

[0 2 4 6 8]

# arange는 range와 동일하게 시작,끝,간격(step size)를 지정 할 수 있고 추가로 dtype도 정의 할 수 있다.
import numpy as np

arr2 = np.linspace(0,10, num=5)

print(arr2)

[ 0.   2.5  5. 7.5 10. ]

# num=5를 통해 5회에 걸쳐 나눠진 값을 반환한다.

 

 


 

원소 정렬

 

 

 

import numpy as np

arr = np.array([[2, 1, 5, 3, 7],[4,6,3,2,7]])
arr = np.sort(arr,0)
print(arr)
[[2 1 3 2 7]
 [4 6 5 3 7]]
import numpy as np

arr = np.array([[2, 1, 5, 3, 7],[4,6,3,2,7]])
arr = np.sort(arr,1)
print(arr)
[[1 2 3 5 7]
 [2 3 4 6 7]]

 

파이썬에서 올림 차순을 하기 위해 배웠던 sort를 동일하게 사용하는데, 함수를 호출할 때 축(0,1,...), 종류, 순서를 지정할 수 있다.

 

 

  • argsort : 하나 이상의 키를 기준으로 데이터 정렬
  • lexsort : 여러 키를 기준으로 데이터 정렬(나중에 넘겨준 배열이 기준이 되어 데이터 정렬)
  • searchsorted : 정렬된 배열에서 요소 찾기
  • partition : 부분 정렬

 

sort 함수 외에도 위와같이 여러 종류의 정렬 방법이 있으니 참고하자.

 

 

 

원소 추가

 

 

np.concatenate() 는 기존 축을 따라 배열 시퀀스를 결합해주는 함수이다.

 

numpy.concatenate((arr1, arr2,...), axis=0, out=None, dtype=, casting)

 

arr1, arr2 라는 배열의 합쳐질 축을 제외한 나머지 축이 동일한 모양이라면 이 배열은 합칠 수 있다.

 

 

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

arr_concat = np.concatenate((arr1,arr2))

print(arr_concat)
[1 2 3 4 5 6 7 8]

 

concatenate() 함수는 몇 가지 제약이 있으니 주의하여 사용하자

 

  • (arr1, arr2,...) 결합하고자 하는 배열은 합쳐질 축을 제외하고 나머지 축은 동일한 모양 이어야 한다.
  • axis : [선택] 배열이 결합되는 축이 None이면 1차원 배열이며, 기본값은 0이 된다.
  • out : [선택] 결합된 배열의 출력 모양을 나타낸다, 작성된 배열은 출력 배열과 동일해야 한다.
  • 2차원 이상부터는 의도에 맞게 축을 지정해야 한다. 기본값은 0

 

 

원소 제거

 

 

numpy.delete(arr, obj, axis=None)

 

del 키워드 역시 파이썬 기초 문법에서 다뤘으나 np에서 사용되는 delete는 그 사용법이 조금 다르다.

 

지정한 키워드를 삭제하는 것이 아닌, 그 하위 배열이 삭제되기 때문이다.

 

arr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(arr)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]


arr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
arr = np.delete(arr, 1, 0)
print(arr)
[[ 1  2  3  4]
 [ 9 10 11 12]]


arr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
arr = np.delete(arr, [1,3,5], None)
print(arr)
[ 1  3  5  7  8  9 10 11 12]

 

numpy.delete(arr, obj, axis=None)

 

  • arr : 배열 입력
  • obj : 슬라이스, 정수 또는 정수 배열, 지정된 축의 하위 배열을 제거하기 때문에 상위 배열을 표기한다.
  • axis : [선택] 정수 형태. obj에 의해 정의된 하위 배열에서 삭제할 축을 입력, 입력하지 않을 시 기본값은 None으로         1차원 배열로 변환된 후 해당 요소를 삭제한다. 
  • obj에 인덱싱을 사용하여 요소 제거도 가능하다.