np.arrange(n) //n까지 저장하는 numpy 배열
data = np.random.randn(2,3) //2*3 만큼의 ndarray 생성
data.shape //몇 곱하기 몇 배열인지
data.dtype //안에 무슨 자료형이 들어있는지
np.array(파이썬 배열) //파이썬 배열을 numpy 배열로 변환 가능
np.zeros(10) //길이 10의 0으로 구성된 배열
np.zeros((3, 6)) //3 * 6, 0으로 구성된 이차원 배열
np.zeros((2, 3, 2)) //2 * 3 * 2, 0으로 구성된 삼차원 배열
np.arrange(15) //0부터 14까지 있는 일차원 배열
arr1 = np.array([1,2,3], dtype=np.int32) //배열의 원소 데이터 타입을 int32로 명시
arr1.astype(float) //배열의 원소 타입을 float로 변경
배열의 중요한 특징은 for문 없이 데이터를 일괄 처리할 수 있다는 것
이를 벡터화라고 함
같은 크기의 배열 간의 산술 연산은, 각 배열의 각 원소 단위로 적용
numpy 배열에 슬라이싱으로 배열 조각을 가져올 수 있고, 여기에 스칼라값을 대입하면, 해당 영역의 값들이 전파(또는 브로드캐스팅) 된다.
이때 배열 조각에 대한 변형은 원본 배열에 반영된다.
numpy의 다차원 배열에 접근 할 때는, 인덱스를 콤마로 구분해도 된다.
In [60]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
In [61]: data = np.random.randn(7, 4)
In [62]: names
Out[62]: array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4')
In [63]: data
Out[63]:
array([[-1.09449543, 1.33842269, 0.4367005 , 0.45852453],
[ 0.71963332, -1.25159804, -0.35109454, -0.85526839],
[ 0.01268187, 0.46265082, -1.03517927, -0.2739274 ],
[ 0.327757 , 0.0494705 , -1.06467629, -1.1558889 ],
[ 1.58155799, -0.99390044, 0.36420652, -1.75531138],
[-0.929551 , -0.40280585, 0.5611649 , -0.19757007],
[ 1.02814787, 1.23568885, 0.22188382, -0.38510986]])
In [64]: names == 'Bob'
Out[64]: array([ True, False, False, True, False, False, False])
In [65]: data[names=='Bob']
Out[65]:
array([[-1.09449543, 1.33842269, 0.4367005 , 0.45852453],
[ 0.327757 , 0.0494705 , -1.06467629, -1.1558889 ]])
//특정한 순서로 로우 선택 가능
In [74]: arr
Out[74]:
array([[0., 0., 0., 0.],
[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.],
[6., 6., 6., 6.],
[7., 7., 7., 7.]])
In [75]: arr[[4, 3, 0, 6]]
Out[75]:
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
팬시 색인은 슬라이싱과 달리, 선택된 데이터를 새로운 배열로 복사한다
arr.reshape(튜플) //다차원 배열을 원하는 형태로 재구성
arr.T //이차원 배열을 전치. 행과 열을 바꿈
np.dot(arr.T, arr) //행렬의 내적
arr.transpose(튜플) //축 번호를 원하는대로 바꿈
arr.swapaxes(1,2) //축 번호를 받아서 배열을 뒤바꿈?
In [4]: arr
Out[4]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [5]: np.sqrt(arr)
Out[5]:
array([0. , 1. , 1.41421356, 1.73205081, 2. ,
2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])
In [6]: np.exp(arr)
Out[6]:
array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,
5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,
2.98095799e+03, 8.10308393e+03])
sqrt, exp 등의 함수는 기본적으로 전체 원소에 적용된다. 이런걸 단항 유니버설 함수라고 한다.
In [9]: x
Out[9]:
array([ 0.13334442, 0.47961467, 0.34854219, -1.15060949, 0.67819017,
-1.0815493 , -1.85802155, -1.00336541])
In [10]: y
Out[10]:
array([-0.40564506, -0.12126072, 1.03362326, 1.02822596, -1.18462256,
0.91493542, 0.62956396, 0.71171703])
In [11]: np.maximum(x,y)
Out[11]:
array([0.13334442, 0.47961467, 1.03362326, 1.02822596, 0.67819017,
0.91493542, 0.62956396, 0.71171703])
In [12]: np.add(x,y)
Out[12]:
array([-0.27230064, 0.35835395, 1.38216545, -0.12238353, -0.50643239,
-0.16661389, -1.22845759, -0.29164838])
add, maximum은 배열을 반환한다
In [14]: arr
Out[14]:
array([ -1.38433615, -1.08860093, 0.43396342, -13.07077085,
-2.6481159 , -0.14308658, 2.23040492])
In [15]: remainder, whole_part = np.modf(arr)
In [16]: remainder
Out[16]:
array([-0.38433615, -0.08860093, 0.43396342, -0.07077085, -0.6481159 ,
-0.14308658, 0.23040492])
In [17]: whole_part
Out[17]: array([ -1., -1., 0., -13., -2., -0., 2.])
몫과 나머지로 다른 두개 이상의 배열을 반환하는 함수도 있다.
In [19]: points = np.arange(-5, 5, 0.01)
In [20]: xs, ys = np.meshgrid(points, points)
//meshgrid는 두 개의 1차원 배열을 받아서,
(x,y) 순서쌍을 만들 수 있는 2차원 배열 두 개를 반환한다
In [21]: ys
Out[21]:
array([[-5. , -5. , -5. , ..., -5. , -5. , -5. ],
[-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],
[-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],
...,
[ 4.97, 4.97, 4.97, ..., 4.97, 4.97, 4.97],
[ 4.98, 4.98, 4.98, ..., 4.98, 4.98, 4.98],
[ 4.99, 4.99, 4.99, ..., 4.99, 4.99, 4.99]])
In [22]: xs
Out[22]:
array([[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
...,
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99]])
In [23]: z = np.sqrt(xs ** 2 + ys ** 2)
//sqrt 함수를 이용해 모든 이차원 배열의 원소에 대해 연산을 시행
In [24]: z
Out[24]:
array([[7.07106781, 7.06400028, 7.05693985, ..., 7.04988652, 7.05693985,
7.06400028],
[7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,
7.05692568],
[7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,
7.04985815],
...,
[7.04988652, 7.04279774, 7.03571603, ..., 7.0286414 , 7.03571603,
7.04279774],
[7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,
7.04985815],
[7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,
7.05692568]])
In [30]: xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
In [31]: yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
In [32]: cond = np.array([True, False, True, True, False])
//기본 파이썬의 리스트 표기법을 사용한 예
In [33]: result = [(x if c else y) for x,y,c in zip(xarr, yarr, cond)]
In [34]: result
Out[34]: [1.1, 2.2, 1.3, 1.4, 2.5]
//numpy의 where를 활용한 예
In [35]: result = np.where(cond, xarr, yarr)
In [36]: result
Out[36]: array([1.1, 2.2, 1.3, 1.4, 2.5])
In [37]: arr = np.random.randn(4, 4)
In [38]: arr
Out[38]:
array([[ 0.24329842, -0.30894191, 1.06130437, 1.13809259],
[-2.25949561, -1.02842952, -0.38979807, -0.32690165],
[ 2.21799434, -0.63429216, -0.59617981, -0.17275839],
[ 0.42650363, 2.04844863, 0.66940995, -0.83949312]])
In [39]: np.where(arr>0, 2, -2)
Out[39]:
array([[ 2, -2, 2, 2],
[-2, -2, -2, -2],
[ 2, -2, -2, -2],
[ 2, 2, 2, -2]])
arr.mean()
np.mean(arr) //둘다 평균 리턴
arr.sum() //합 리턴
arr.mean(axis=1)
arr.sum(axis=0) //원하는 axis에 대한 통계만 계산
//cumsum과 cumprod는 중간 계산값을 담고 있는 배열을 반환
//rod는 누적곱
In [45]: arr = np.array([1, 2, 3, 4, 5, 6, 7])
In [46]: arr.cumsum()
Out[46]: array([ 1, 3, 6, 10, 15, 21, 28])
In [48]: arr
Out[48]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [49]: arr.cumprod(axis=0)
Out[49]:
array([[ 0, 1, 2],
[ 0, 4, 10],
[ 0, 28, 80]])
In [50]: arr.cumprod(axis=1)
Out[50]:
array([[ 0, 0, 0],
[ 3, 12, 60],
[ 6, 42, 336]])
In [52]: arr = np.random.randn(100)
In [54]: (arr>0).sum()
Out[54]: 48
//arr>0 이라는 조건을 이용해, 0과 1로만 이루어진 배열로 강제로 바꾼다.
//이 배열의 총합을 구하면, 조건에 맞는 원소의 수를 카운트할 수 있다.
In [55]: bools = np.array([False, False, True, False])
In [56]: bools.any() //bool 배열에서 하나 이상의 값이 True인지 확인
Out[56]: True
In [57]: bools.all() //bool 배열에서 모든 값이 True인지 확인
Out[57]: False
In [59]: arr
Out[59]:
array([ 0.49588864, -0.3139628 , 1.5493912 , 0.34864308, 0.01327596,
1.50687672])
In [60]: arr.sort()
In [61]: arr
Out[61]:
array([-0.3139628 , 0.01327596, 0.34864308, 0.49588864, 1.50687672,
1.5493912 ])
In [62]: arr = np.random.randn(5,3)
In [63]: arr
Out[63]:
array([[-1.07267959, 0.77191415, -0.423504 ],
[ 0.66999513, -2.22217556, -0.70034757],
[ 1.47669576, -0.09384004, 0.88055938],
[-0.28634861, 0.1511579 , -0.31502024],
[-0.44688005, -0.12262832, -0.15140229]])
In [64]: arr.sort(1)
In [65]: arr
Out[65]:
array([[-1.07267959, -0.423504 , 0.77191415],
[-2.22217556, -0.70034757, 0.66999513],
[-0.09384004, 0.88055938, 1.47669576],
[-0.31502024, -0.28634861, 0.1511579 ],
[-0.44688005, -0.15140229, -0.12262832]])
In [66]: arr.sort(0)
In [67]: arr
Out[67]:
array([[-2.22217556, -0.70034757, -0.12262832],
[-1.07267959, -0.423504 , 0.1511579 ],
[-0.44688005, -0.28634861, 0.66999513],
[-0.31502024, -0.15140229, 0.77191415],
[-0.09384004, 0.88055938, 1.47669576]])
sort는 배열을 직접 변경하지 않고, 복사본을 반환
배열의 분위수를 구하는 빠른 방법은, 배열을 정렬한 후, 특정 분위의 값을 선택하는 것이다
In [68]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
In [69]: np.unique(names) //중복 제거 함수
Out[69]: array(['Bob', 'Joe', 'Will'], dtype='<U4')
In [70]: sorted(set(names)) //파이썬으로 구현한 집합 제거
Out[70]: ['Bob', 'Joe', 'Will']
unique(x) //배열에서 중복된 원소를 제거한 뒤 정렬하여 반환
intersect1d(x,y) //배열 x와 y에 공통적으로 존재하는 원소를 정렬하여 반환
union1d(x,y) //두 배열의 합집합 반환
in1d(x,y) //x의 원소가 y의 원소에 포함되는지 나타내는 bool 배열 반환
setdiff1d(x,y) //x와 y의 차집합을 반환
setxor1d(x,y) //한 배열에는 포함되지만, 두 배열 모두에 포함되지는 않는 원소들의 집합 반환(대칭차집합)
In [71]: arr = np.arange(10)
//배열 저장
In [72]: np.save('some_array', arr) //확장자를 붙이지 않으면 자동으로 npy를 붙여줌
//배열 불러오기
In [73]: np.load('some_array.npy')
Out[73]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
//키워드 인자 형태로 여러 배열을 입력, 압축해서 저장
In [74]: np.savez('array_archive.npz', a=arr, b=arr)
//불러오면 딕셔너리 형태의 객체로 저장됨
In [75]: arch = np.load('array_archive.npz')
//키로 접근 가능
In [76]: arch['b']
Out[76]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [77]: arch['a']
Out[77]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
//압축이 잘 되는 형식의 데이터라면 compressed를 붙인 함수를 이용
In [78]: np.savez_compressed('arrys_compressed.npz', a=arr, b=arr)
행렬의 곱셈, 분할, 행렬식, 그리고 정사각 행렬 수학 같은 선형대수는, 배열을 다루는 라이브러리에서 중요한 부분이다.
두 개의 2차원 배열을 * 연산자로 곱하면, 행렬곱이 아니라 대응하는 각각 원소의 곱을 계산한다.
행렬 곱셈은, 배열 메서드이자 numpy 네임스페이스 안에 있는 dot 함수를 이용해 계산한다.
In [79]: x = np.array([[1.,2.,3.], [4.,5.,6.]])
In [80]: y = np.array([[6., 23.], [-1, 7], [8,9]])
In [81]: x
Out[81]:
array([[1., 2., 3.],
[4., 5., 6.]])
In [82]: y
Out[82]:
array([[ 6., 23.],
[-1., 7.],
[ 8., 9.]])
In [83]: x.dot(y) //행렬곱
Out[83]:
array([[ 28., 64.],
[ 67., 181.]])
In [84]: np.dot(x,y) //행렬곱의 다른 표현
Out[84]:
array([[ 28., 64.],
[ 67., 181.]])
//2차원 배열과 곱셈이 가능한 크기의 1차원 배열 간의 행렬 곱셈의 결과는 1차원 배열
In [86]: np.dot(x, np.ones(3))
Out[86]: array([ 6., 15.])
In [87]: x @ np.ones(3) //@로 행렬 곱셈을 수행할 수 있음
Out[87]: array([ 6., 15.])
행렬의 분할과 역행렬, 행렬식과 같은 것들 포함하고 있음
In [88]: samples = np.random.normal(size= (4, 4))
//normal을 사용하면, 표준 정규분포로부터 표본을 생성할 수 있음
In [89]: samples
Out[89]:
array([[ 0.43673236, 0.89294536, 0.4536767 , -1.18139694],
[-0.60390971, 0.19476738, 1.48935697, 0.74082633],
[ 0.91817605, -0.60832071, 2.19186236, -0.67472785],
[-1.39867968, -1.10843721, 0.19343346, -0.1347002 ]])
In [90]: np.random.seed(1234) //numpy.random에서 사용하는 시드값을 바꿀 수 있음
In [91]: rng = np.random.RandomState(123)
//RandomState로, 원하는 시드값을 가지는 격리된 난수 생성기를 만들 수 있음
In [92]: rng.randn(10)
Out[92]:
array([-1.0856306 , 0.99734545, 0.2829785 , -1.50629471, -0.57860025,
1.65143654, -2.42667924, -0.42891263, 1.26593626, -0.8667404 ])
In [93]: np.random.randn(10)
Out[93]:
array([ 0.47143516, -1.19097569, 1.43270697, -0.3126519 , -0.72058873,
0.88716294, 0.85958841, -0.6365235 , 0.01569637, -2.24268495])
seed | 난수 생성기의 시드 지정 |
---|---|
permutation | 순서를 임의로 바꾸거나 임의의 순열을 반환 |
shuffle | 리스트나 배열의 순서를 뒤섞음 |
rand | 균등분포에서 표본을 추출 |
randint | 주어진 최소/최대 범위 안에서 임의의 난수 추출 |
randn | 표준편차가 1이고 평균값이 0인 정규분포 안에서 표본 추출 |
binomial | 이항분포에서 표본을 추출 |
normal | 정규분포(가우시안)에서 표분 추출 |
beta | 베타분포에서 표본 추출 |
chisquare | 카이제곱분포에서 표본 추출 |
gamma | 감마분포에서 표본 추출 |
uniform | 균등 [0, 1) 분포에서 표본 추출 |
In [103]: def stairs():
...: position = 0
...: walk = [position]
...: steps = 100
...: for i in range(steps):
...: step = 1 if random.randint(0,1) else -1
...: position += step
...: walk.append(position)
...: return walk
...:
In [104]: stairs()
np.random.randint(a, b) //a 이상 b 미만의 랜덤 정수
np.where(bool 배열, a, b) //bool 배열의 값이 true면 a, false면 b인 배열 반환