데이터 분석

데이터 처리를 위한 numpy

창민이 개발일지 2022. 6. 17. 11:24

데이터 처리를 위한 numpy

 
▣ Numpy

넘파이(Numpy)는 수치 데이터를 다루는 파이썬 패키지입니다.
Numpy의 핵심이라고 불리는 다차원 행렬 자료구조인 ndarray를 통해 벡터 및 행렬을 사용하는 선형 대수 계산에서 주로 사용됩니다.
Numpy는 편의성뿐만 아니라, 속도면에서도 순수 파이썬에 비해 압도적으로 빠르다는 장점이 있습니다.
인공지능 관련 라이브러리는 거의 numpy과 관련되서 반환한다.

In [4]:
import numpy as np

array

  • 리스트를 numpy배열(ndarray)로 생성
In [5]:
ndarray = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])

1) numpy 배열

arrange

  • np.arange()는 지정해준 범위에 대해서 배열을 생성합니다. 
  • numpy.arange(start, stop, step, dtype)
  • start부터 stop-1까지 step씩 증가하는 dtype 타입의 배열.
In [3]:
print(np.arange(5,9,1),"\n")
print(np.arange(5))
[5 6 7 8] 

[0 1 2 3 4]

ndim, shape, size

  • ndim: 차원 
  • shape: 형태 
  • size: 크기
In [7]:
print(ndarray.ndim)
print(ndarray.shape)
print(ndarray.size)
2
(3, 4)
12
 

2) ndarray 초기화

zeros()는 해당 배열에 모두 0을 삽입합니다.
ones()는 모두 1을 삽입합니다.
full()은 배열에 사용자가 지정한 값을 넣는데 사용
eye()는 대각선으로는 1이고 나머지는 0인 2차원 배열을 생성합니다.

In [4]:
print(np.zeros([3,3]),"\n")
print(np.ones([3,3]),"\n")
print(np.full([3,3],7),"\n")
print(np.eye(3))
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]] 

[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]] 

[[7 7 7]
 [7 7 7]
 [7 7 7]] 

[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
 

3) ndarray 슬라이싱

In [5]:
ndarray
Out[5]:
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])
In [6]:
print(ndarray[:,:],"\n")
print(ndarray[:,2:],"\n")
print(ndarray[:2,:],"\n")
print(ndarray[2,3])
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]] 

[[ 3  4]
 [ 7  8]
 [11 12]] 

[[1 2 3 4]
 [5 6 7 8]] 

12

3.1) 두개의 배열을 같은 순서로 무작위 섞기

In [7]:
# 0 ~ 9까지 숫자를 두 개의 배열에 같은 순서로 저장합니다. 
X = np.arange(0, 10)
Y = np.arange(0, 10)

# 배열의 원소 개수만큼 인덱스 배열을 만든 후 
idx = np.arange(X.shape[0])
# 무작위로 뒤섞어 줍니다. 
np.random.shuffle(idx)

# X, Y 두 배열을 같은 순서로 섞어줍니다. 
X = X[idx]
Y = Y[idx]

print(X,Y)
[3 0 5 4 2 6 7 1 8 9] [3 0 5 4 2 6 7 1 8 9]
 

4) random

시드 설정하기

컴퓨터 프로그램에서 발생하는 무작위 수는 사실 엄격한 의미의 무작위 수가 아니다. 어떤 특정한 시작 숫자를 정해 주면 컴퓨터가 정해진 알고리즘에 의해 마치 난수처럼 보이는 수열을 생성한다. 이런 시작 숫자를 시드(seed)라고 한다. 일단 생성된 난수는 다음번 난수 생성을 위한 시드값이 된다. 따라서 시드값은 한 번만 정해주면 된다.

시드는 보통 현재 시각등을 이용하여 자동으로 정해지지만 사람이 수동으로 설정할 수도 있다. 특정한 시드값이 사용되면 그 다음에 만들어지는 난수들은 모두 예측할 수 있다.

In [ ]:
np.random.seed(500) # 시드 값 지정

난수 생성 모듈

np.random.randint : 균일분포의 정수 난수 1개 생성
np.random.rand : 0 ~ 1사이의 균일 분포에서 난수 matrix array 생성
np.random.randn : 가우시안 표준 정규 분포(정규분포)에서 난수 matrix array 생성
np.random.uniform(min, max, N) : 균일분포로 array 호출
np.random.normal(평균, 편차, 개수) : 정규분포로 array 호출

In [11]:
np.random.randn(2,3)
Out[11]:
array([[-1.03225822e-03,  1.67233773e-01, -1.33210901e-01],
       [ 1.02193612e+00, -1.47320409e+00,  7.41391073e-01]])
In [21]:
# 균일분포 생성
print(np.random.randint(99))

 

 

정규분포 난수 생성

In [62]:
np.random.normal(5,2,[2,5])
Out[62]:
array([-5. , -4.9, -4.8, -4.7, -4.6, -4.5, -4.4, -4.3, -4.2, -4.1, -4. ,
       -3.9, -3.8, -3.7, -3.6, -3.5, -3.4, -3.3, -3.2, -3.1, -3. , -2.9,
       -2.8, -2.7, -2.6, -2.5, -2.4, -2.3, -2.2, -2.1, -2. , -1.9, -1.8,
       -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1. , -0.9, -0.8, -0.7,
       -0.6, -0.5, -0.4, -0.3, -0.2, -0.1,  0. ,  0.1,  0.2,  0.3,  0.4,
        0.5,  0.6,  0.7,  0.8,  0.9,  1. ,  1.1,  1.2,  1.3,  1.4,  1.5,
        1.6,  1.7,  1.8,  1.9,  2. ,  2.1,  2.2,  2.3,  2.4,  2.5,  2.6,
        2.7,  2.8,  2.9,  3. ,  3.1,  3.2,  3.3,  3.4,  3.5,  3.6,  3.7,
        3.8,  3.9,  4. ,  4.1,  4.2,  4.3,  4.4,  4.5,  4.6,  4.7,  4.8,
        4.9,  5. ])

정규 분포

In [25]:
x = np.linspace(-5, 5, 101)   # x 정의
x
Out[25]:
array([-5. , -4.9, -4.8, -4.7, -4.6, -4.5, -4.4, -4.3, -4.2, -4.1, -4. ,
       -3.9, -3.8, -3.7, -3.6, -3.5, -3.4, -3.3, -3.2, -3.1, -3. , -2.9,
       -2.8, -2.7, -2.6, -2.5, -2.4, -2.3, -2.2, -2.1, -2. , -1.9, -1.8,
       -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1. , -0.9, -0.8, -0.7,
       -0.6, -0.5, -0.4, -0.3, -0.2, -0.1,  0. ,  0.1,  0.2,  0.3,  0.4,
        0.5,  0.6,  0.7,  0.8,  0.9,  1. ,  1.1,  1.2,  1.3,  1.4,  1.5,
        1.6,  1.7,  1.8,  1.9,  2. ,  2.1,  2.2,  2.3,  2.4,  2.5,  2.6,
        2.7,  2.8,  2.9,  3. ,  3.1,  3.2,  3.3,  3.4,  3.5,  3.6,  3.7,
        3.8,  3.9,  4. ,  4.1,  4.2,  4.3,  4.4,  4.5,  4.6,  4.7,  4.8,
        4.9,  5. ])

f(x)=12πσe−(x−β)22σ2

In [79]:
y = (1 / np.sqrt(2 * np.pi)) * np.exp(- x ** 2 / 2 ) # 표준 정규 분포 
In [76]:
plt.figure(figsize=(10, 6))          # 플롯 사이즈 지정
plt.plot(x, y)                       
plt.xlabel("x")                      # x축 레이블 지정
plt.ylabel("y")                      # y축 레이블 지정
plt.grid()                           # 플롯에 격자 보이기
plt.title("Normal Distribution without scipy")     # 타이틀 표시
plt.legend(["N(0, 1)"])              # 범례 표시
plt.show()                           # 플롯 보이기

무작위로 샘플(행 번호) 섞기

In [30]:
data = np.arange(0,50)
data[np.random.permutation(50)]
Out[30]:
array([44,  7, 48, 49,  1, 21, 17, 30, 29, 45, 15, 10, 38, 20, 42, 46,  5,
       28, 47, 13, 34, 39, 18, 35, 36, 25, 40,  8,  6,  0, 32, 14, 41,  9,
       33, 24, 26, 31, 22, 12, 19,  3,  4, 37, 16, 23, 27, 43,  2, 11])

5) 배열 붙이기

In [12]:
a = np.array([[1],[2],[3]]) # (3,1)
b = np.array([[4],[5],[6]]) # (3,1)

print(np.concatenate((a,b))) # axis=0 -> (3,1) + (3,1) = (6,1)
print()
print(np.concatenate((a,b),axis=1)) # axis=1 -> (3,1) + (3,1) = (3,2)
[[1]
 [2]
 [3]
 [4]
 [5]
 [6]]

[[1 4]
 [2 5]
 [3 6]]
 

6) 차원

6.1) 차원 축소 및 확대

In [15]:
a = np.array([[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]])#[1,4,3] -> [4,3]
print(a.shape)

# 축소
print(np.squeeze(a).shape) # squeeze 는 불필요한 차원(1)을 제거 해서 보여줌 
print(np.squeeze(a).shape) # squeeze 는 크기의 변화가 없음

# 확대
print(np.reshape(a,[1,4,3]).shape) # expand_dims 차원을 한계 높인다.
print(np.expand_dims(a,axis=1).shape) # expand_dims 는 크기의 변화가 없음
(1, 4, 3)
(4, 3)
(4, 3)
(1, 4, 3)
(1, 1, 4, 3)
In [14]:
x = np.array([[[[[[[1,2,3,4,5,6,7]]]]]]])
print("차원수:",x.shape)
x = np.squeeze(x)
print("차원수:",x.shape)
차원수: (1, 1, 1, 1, 1, 1, 7)
차원수: (7,)
 

7) 타입 확인 및 타입 변경

In [43]:
a = np.array([True,False,False,True,False])

print(a.dtype)
print(a)
print(a.astype(int))
print(a.astype(float))
print(a.astype(str))
[ True False False  True False]
[1 0 0 1 0]
[1. 0. 0. 1. 0.]
['True' 'False' 'False' 'True' 'False']
 

8) np.sum 함수의 axis 이해

  • axis는 사용할 배열의 차원 미만의 숫자만 사용할 수 있다.
    ex) ndarray.size => 3 -> axis = 0 or 2
  • 예시를 이용해 직접 작성해서 감각을 느껴라
    ex) [2,8], [2,2,4], [2,2,2,2]
  • axis = -1 는 axis가 가질 수 있는 가장 큰(가장 안쪽) 값을 의미
In [40]:
arr = np.arange(0, 16)
arr = np.reshape(arr,[2,2,2,2])
print(arr)
np.sum(arr,axis=0)
[[[[ 0  1]
   [ 2  3]]

  [[ 4  5]
   [ 6  7]]]


 [[[ 8  9]
   [10 11]]

  [[12 13]
   [14 15]]]]
Out[40]:
array([[[ 8, 10],
        [12, 14]],

       [[16, 18],
        [20, 22]]])
 

9) numpy 배열을 여러개의 하위 배열로 분할하기(split)

In [8]:
x = np.arange(18).reshape(3, 6)
print(x)
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]]
In [12]:
print(np.split(x,3))
print("형태 :",np.shape(np.split(x,3)))
[array([[0, 1, 2, 3, 4, 5]]), array([[ 6,  7,  8,  9, 10, 11]]), array([[12, 13, 14, 15, 16, 17]])]
형태 : (3, 1, 6)
 

10) 차원의 위치 바꾸기

  • transpose
In [13]:
a = np.arange(20).reshape(2, 5, 2)
In [14]:
print(a.shape)
print(a)
(2, 5, 2)
[[[ 0  1]
  [ 2  3]
  [ 4  5]
  [ 6  7]
  [ 8  9]]

 [[10 11]
  [12 13]
  [14 15]
  [16 17]
  [18 19]]]
In [15]:
a = a.transpose([0,2,1])
print(a.shape)
print(a)
(2, 2, 5)
[[[ 0  2  4  6  8]
  [ 1  3  5  7  9]]

 [[10 12 14 16 18]
  [11 13 15 17 19]]]
 

11) 배열에서 특징 값(유일한 값)만 추출 하기

In [5]:
x = np.array([1,2,3,1,1,12,3,3,5,6,7,77])
print(np.unique(x))
print(np.unique(x,return_counts=True))
[ 1  2  3  5  6  7 12 77]
(array([ 1,  2,  3,  5,  6,  7, 12, 77]), array([3, 1, 3, 1, 1, 1, 1, 1]))
 

12) 백분위수 구하기

In [32]:
x = np.arange(0,100,1)
q = np.percentile(x,[0,25,50,75,100])
print(q)
[ 0.   24.75 49.5  74.25 99.  ]