파이썬 (0413) 7주차

numpy
Author

김보람

Published

April 13, 2022

import numpy as np

numpy공부 5단계 : 랜덤모듈

np.random.rand()

- 0~1사이에서 10개의 난수 생성

np.random.rand(10)
array([0.30133684, 0.33047977, 0.37682904, 0.34945581, 0.88634262,
       0.272207  , 0.75103749, 0.55871507, 0.12304257, 0.88020941])

- 0~2사이에서 10개의 난수 생성

np.random.rand(10)*2
array([1.85950286, 0.90618509, 0.3153    , 0.47472741, 1.60545103,
       1.07072774, 1.10650141, 0.77505785, 1.19933414, 1.76222208])

- 1~2사이에서 10개의 난수 생성

np.random.rand(10)+1
array([1.01747795, 1.52789889, 1.29223002, 1.53147587, 1.13455031,
       1.51668185, 1.2430438 , 1.59676278, 1.8731811 , 1.36113831])

- 1~3사이에서 10개의 난수 생성

np.random.rand(10)*2+1    # 1~3
array([2.79324839, 2.37177079, 1.12638737, 1.71767497, 2.95057073,
       1.23158048, 2.56688411, 2.94392262, 1.32675882, 2.29817471])

np.random.randn()

- N(0,1) 에서 10개 추출

np.random.randn(10) # 표준정규분포에서 10개의 샘플 추출
array([ 1.895967  , -0.26215342,  0.87906492,  0.45616171,  1.66244424,
        0.72458419,  0.31057676, -0.55909889,  0.47656554,  0.35143513])

- N(1,1)에서 10개 추출

np.random.randn(10)+1
array([ 1.11007188, -0.44321876,  0.04904333, -0.10478302,  0.13301967,
       -0.49468263,  1.7751611 , -0.84760291,  0.40840343,  0.638133  ])

- N(0,4)에서 10개 추출 (평균이 0이고 분산이 4인 분포)

np.random.randn(10)*2
array([-1.14364925,  2.60415043, -1.65488974, -0.59463897,  0.97607708,
        2.33979589,  3.49290763, -1.50749403, -1.41447157,  0.45852112])

- N(3,4)에서 10개 추출

np.random.randn(10)*2+3
array([ 4.736406  ,  2.35419865,  2.8265146 ,  0.26470966, -0.4240817 ,
        1.00836216,  6.23531314,  3.75134991,  0.60427655, -0.13645246])

np.random.randint()

- [0,7)의 범위에서 하나의 정수를 랜덤으로 생성

np.random.randint(7)   #[0,7)의 범위에서 하나의 정수 생성
3

- [0,7)의 범위에서 20개의 정수를 랜덤으로 생성

np.random.randint(7,size=(20,))  # [0,7)의 범위에서 20개의 정수 생성
array([2, 5, 5, 5, 2, 4, 3, 4, 1, 4, 1, 2, 3, 2, 4, 2, 2, 6, 1, 2])

- [0,7)의 범우에서 (5,5) shape으로 정수를 랜덤으로 생성

np.random.randint(7,size=(5,5))  
array([[1, 6, 2, 5, 0],
       [3, 3, 3, 1, 0],
       [4, 0, 2, 5, 6],
       [1, 0, 1, 2, 0],
       [6, 6, 5, 1, 3]])

- 위와 같은 코드를 아래와 같이 구현가능

np.random.randint(low=7,size=(2,2))  # [0,7)의 범위에서 20개의 정수 생성
array([[2, 4],
       [6, 4]])

- [10,20)의 범위에서 (5,5) shape 정수를 랜덤으로 생성

np.random.randint(low=10, high=20,size=(5,5))  
array([[14, 19, 17, 14, 17],
       [16, 11, 14, 17, 16],
       [12, 11, 18, 17, 14],
       [11, 15, 14, 18, 11],
       [13, 19, 10, 17, 14]])

- 의문: np.random.randint(low=7,size=(5,5)) 가 좀 이상하다. 사실 np.random.randint(high=7,size=(5,5))가 되어야 맞지 않는가?

-> 저도 그렇게 생각하긴 하는데요, 구현이 이렇게 되어있습니다. 도움말 확인!

Return random integers from the "discrete uniform" distribution of the specified dtype in the "half-open" interval [`low`, `high`). If `high` is None (the default), then results are from [0, `low`).

np.random.choice()

- ver1

np.random.choice(5,20)  # [0,5)에서 20개를 뽑음, 중복허용
array([3, 2, 0, 3, 3, 3, 0, 0, 2, 2, 0, 0, 0, 1, 3, 1, 3, 2, 0, 0])
np.random.randint(5, size=(20,))
array([3, 2, 2, 3, 4, 1, 0, 1, 4, 1, 3, 2, 2, 2, 4, 3, 2, 4, 2, 3])

- ver2

np.random.choice([0,1,2,3],20) # [0,1,2,3] 에서 20개를 뽑음 , 중복허용
array([2, 0, 1, 3, 1, 1, 2, 2, 1, 2, 0, 1, 1, 0, 1, 0, 2, 3, 3, 1])
np.random.choice(["apple","orange","banana"],20)
array(['orange', 'banana', 'banana', 'orange', 'banana', 'orange',
       'banana', 'orange', 'apple', 'orange', 'orange', 'apple', 'apple',
       'orange', 'apple', 'apple', 'orange', 'orange', 'apple', 'apple'],
      dtype='<U6')
np.random.choice(["apple","orange","banana"],2,replace=False) # 중복허용 X 
array(['apple', 'orange'], dtype='<U6')

통계분포

np.random.binomial(n=10, p=0.1, size=(5,)) #X1, ..., X5 ~ B(10,0.2)
array([1, 0, 2, 0, 2])
np.random.normal(loc=10,scale=2,size=(5,)) # X1, ..., X5 ~ N(10,4) 
array([8.5617943 , 8.9716337 , 7.90650741, 6.59782362, 7.90620931])
  • np.radom.randn(5)*2 + 10와 같은코드
np.random.uniform(low=2,high=4,size=(5,)) # X1, ..., X5 ~ U(2,4)  #균일분포
array([2.49501161, 3.10469251, 3.89920656, 2.33160764, 2.28406983])
  • np.random.rand(5)*2+2와 같은 코드
np.random.poisson(lam=5,size=(5,)) # X1,...,X5 ~ Poi(5) 
array([5, 5, 7, 4, 6])

nupmy공부 6단계: 기타 유용한 기본기능들

np.where, np.argwhere

a=np.array([0,0,0,1,0])
a
array([0, 0, 0, 1, 0])
np.where(a==1) # 조건 a==1을 만족하는 인덱스를 출력하라
(array([3], dtype=int64),)
np.argwhere(a==1)
array([[3]], dtype=int64)
np.argwhere(a==0)
array([[0],
       [1],
       [2],
       [4]], dtype=int64)

- 2차원

np.random.seed(43052)
a=np.random.randn(12).reshape(3,4)
a
array([[ 0.38342049,  1.0841745 ,  1.14277825,  0.30789368],
       [ 0.23778744,  0.35595116, -1.66307542, -1.38277318],
       [-1.92684484, -1.4862163 ,  0.00692519, -0.03488725]])
np.where(a<0) # 조건을 만족하는 인덱스가 (1,2), (1,3), (2,0), (2,1), (2,3) 이라는 의미
(array([1, 1, 2, 2, 2], dtype=int64), array([2, 3, 0, 1, 3], dtype=int64))
np.argwhere(a<0)  # 조건을 만족하는 인덱스가 (1,2), (1,3), (2,0), (2,1), (2,3) 이라는 의미
array([[1, 2],
       [1, 3],
       [2, 0],
       [2, 1],
       [2, 3]], dtype=int64)
a[np.where(a<0)]  # 조건을 만족하는 인덱스가 모두 출력=> 1차원 array로 출력
array([-1.66307542, -1.38277318, -1.92684484, -1.4862163 , -0.03488725])
a[np.argwhere(a<0)]  # 출력불가능
IndexError: index 3 is out of bounds for axis 0 with size 3
a[np.argwhere(a<0)[0][0],np.argwhere(a<0)[0][1]] # 어거지로 출력할수는 있음 
-1.6630754187023522

- np.where의 특수기능

np.random.seed(43052)
a=np.random.randn(12).reshape(3,4)
a
array([[ 0.38342049,  1.0841745 ,  1.14277825,  0.30789368],
       [ 0.23778744,  0.35595116, -1.66307542, -1.38277318],
       [-1.92684484, -1.4862163 ,  0.00692519, -0.03488725]])
np.where(a<0,0,a)   #a<0을 체크=> 조건에 맞으면 0, 조건에 안맞으면 a 출력
array([[0.38342049, 1.0841745 , 1.14277825, 0.30789368],
       [0.23778744, 0.35595116, 0.        , 0.        ],
       [0.        , 0.        , 0.00692519, 0.        ]])
np.where(a<0,0,1) # #a<0을 체크=> 조건에 맞으면 0, 조건에 안맞으면 1 출력
array([[1, 1, 1, 1],
       [1, 1, 0, 0],
       [0, 0, 1, 0]])

- 요약 - np.where : 인덱스의 좌표를 읽는 가독성은 떨어짐. 그러나 조건에 맞는 원소를 출력하거나 조건에 맞는 특수기능을 처리하는 목적으로 좋은 함수 - np.argwhere : 인덱스의 좌표를 읽는 가독성은 좋은 편임. 그러나 조건에 맞는 원소를 출력하거나 처리하는 기능은 떨어짐

인덱싱고급

- 원래 a는 2d array

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

- 경우 1: 인덱싱 결과가 1d array로 나올 수 있음

a[0,:] # 인덱싱의 결과 축의 갯수가 바뀐다. 2d array -> 1d array
array([0, 1, 2, 3])

- 경우2: 인덱싱 결과가 2d array로 나올 수 있음

a[[0,1],:] # 이것은 축의 숫자가 유지됨 2d array-> 2d array
array([[0, 1, 2, 3],
       [4, 5, 6, 7]])

- 경우1의 상황에서도 축의 갯수를 유지하면서 인덱싱하려면?

a[[0],:] # 인덱싱의 결과 축의 갯수가 유지된다. 2d array->2d array
array([[0, 1, 2, 3]])

- 미묘한 차이를 이해할 것

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

np.ix_

- 아래의 인덱싱을 비교하자

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

- 언뜻 생각하면 위의 결과와 a[[0,1],[0,1]의 결과가 동일할 것 같다.

a[[0,1],[0,1]]
array([0, 5])
  • 실제로는 [a[0,0],a[1,1]]이 array로 나옴

- 사실 np.where에서 이미 관찰하였음

a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
np.where(a % 5 ==0)
(array([0, 1, 2], dtype=int64), array([0, 1, 2], dtype=int64))
a[np.where(a % 5 ==0)]
array([ 0,  5, 10])
a[[0, 1, 2],[0, 1, 2]]
array([ 0,  5, 10])

- a[[0,1],[0,1]]이 a[0:2,0:2]를 의미하게 하려면 아래와 같이 하면 된다.

a[np.ix_([0,1],[0,1])] # 유용해보이지만 생각보다 잘 쓰이는건 아님 
array([[0, 1],
       [4, 5]])

(숙제)

np.random.uniform(low=1.3,high=1.7,size=(10,))
array([1.65411132, 1.42531485, 1.54567744, 1.44735207, 1.33217747,
       1.48856969, 1.47329978, 1.38976795, 1.30469965, 1.66634909])

위와 같은코드를 np.random.rand()를 이용하여 구현하라.