Numpy

6 minute read

Numpy

DataAnalysis을 들어가기 앞서 선행적으로 꼭 필요한 개념인 Numpy에 대해 알아보자.

Vector, Matrix, Multi Array등 과학계산 컴퓨팅에 있어 필수 도구 이다. 입력값 세트를 통해 계산이 반복될 때, 배열로 데이터를 나타내는 것이 자연스럽고 장점이 많다.
과학계산 환경에서 배열을 다루기 좋은 도구로 제공하는 라이브러리가 Numpy이다.
Numpy특징

  1. C언어로 구현되어있어 효율적인 기능들을 제공하고 속도 또한 빠르다.
  2. Array를 제공하므로 Slicing, Broadcasting이 가능하다.
  3. Broadcasting은 크기가 다른 배열 간의 연산을 말한다.
  4. 동일한 자료형만 담을 수 있다는 단점 존재
pip install numpy

명령어를 통하여 설치하고 사용할 수 있다.

Numpy 사용예제

1
2
3
4
5
6
7
8
9
10
import numpy as np

ss = ['tom', 'james', 'oscar']
print(ss,' ', type(ss))
ss2 = np.array(ss)
print(ss2,' ', type(ss2))

li = list(range(1, 11))
print(li)
print(id(li[0]), id(li[1]))
['tom', 'james', 'oscar']   <class 'list'>
['tom' 'james' 'oscar']   <class 'numpy.ndarray'>

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
140707086623376 140707086623408


하나의 List안의 두개의 원소가 서로 다른 주소가지고 있는 것을 알 수 있다.

1
2
3
4
5
6
7
for i in li:
    print(i * 10, end = " ")
    
num_arr = np.array(li)
print(num_arr)
print(id(num_arr[0]), id(num_arr[1]))
print(num_arr * 10)


10 20 30 40 50 60 70 80 90 100 [ 1  2  3  4  5  6  7  8  9 10]
2252689200544 2252689200544
[ 10  20  30  40  50  60  70  80  90 100]

Numpy는 하나의 List안의 두개의 원소가 서로같은 주소 를가지고 있는 것을 알 수 있다.
num_arr * 10와 같이 for문을 실행하지 않아도 같은 결과를 얻을 수 있다.

1
2
3
4
5
6
7
8
9
10
a = np.array([1,2,3])
print(a)
print(type(a))
print(a.dtype)
print(a.shape)
print(a.ndim)
print(a.size)

b = np.array([[1,2,3],[4,5,6]])
print(b.shape)


<class 'numpy.ndarray'>
int32
(3,)
1
3
(2, 3)
typendarray
shape배열의 구조
ndim배열이 차원
size배열의 크기



1
2
3
4
5
6
7
8
a = np.zeros((2,2))
print(a)
b = np.ones((2,2))
print(b)
c = np.full((2,2), 7)
print(c)
d = np.eye(3)
print(d)


[[0. 0.]
 [0. 0.]]
[[1. 1.]
 [1. 1.]]
[[7 7]
 [7 7]]
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
zeros()행렬의 원소를 모두 0으로 설정
ones()행렬의 원소를 모두 1로 설정
full((x,y),z)모든 원소가 z인 x행 y열 함수 배열 생성
eye(x)x행 x열 단위행렬



1
2
3
np.random.seed(0)
print(np.random.rand(5))
print(np.random.randn(5))


[0.5488135  0.71518937 0.60276338 0.54488318 0.4236548 ]
[-0.84272405  1.96992445  1.26611853 -0.50587654  2.54520078]
np.random.rand(x)0~1 사이의 난수 x 개 균등분포로 생성
np.random.randn(x)0~1 사이의 난수 x개 정규분포로 생성
np.random.seed(x)Random의 결과가 같게 설정



1
2
f = {i:np.random.randn() for i in range(5)}
print(f)


{0: 1.0808119130554454, 1: 0.48431215412066475, 2: 0.5791404787067285, 3: -0.18158257273119596, 4: 1.4102046311312142}

향상된 For문과 Numpy를 활용한 Dict Type 배열 만들기

1
2
3
4
5
6
7
8
# Slicing
a = np.array([1,2,3,4,5])
print(a[1:5:2]) # start:end:stack

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


[2 4]
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
[[ 5  6  7  8]
 [ 9 10 11 12]]

Numpy는 Array를 지원하므로 Slicing을 지원한다.
Numpy에는 Index로 접근한다
a[1:5:2] => 1~5까지의 원소를 2개에 하나씩 출력해라

1
2
3
4
b = a[:2, 1:3]
print(b)
print(b[0, 0])
print(a[0, 1])


[[2 3]
 [6 7]]
2
2

Sub Array란 기존의 배열로부터 새로운 배열을 만들어내는 것 이다.

Numpy는 Array를 지원하므로 Slicing을 지원한다.
Numpy에는 Index로 접근한다
a[1:5:2] => 1~5까지의 원소를 2개에 하나씩 출력해라

1
2
3
4
b[0,0] = 77
print(b[0, 0])
print(a[0, 1])
print(a)


77
77
[[ 1 77  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

Sub Array의 값을 변형시키면 원래 Array의 값도 같이 변하게 된다.

1
2
3
4
x = np.array([[1,2],[3,4]])
print(x.dtype)
x = np.array([[1,2],[3,4]], dtype=np.float64)
print(x.dtype)


int32
float64

np.array로 선언할때 dtype을 통하여 원소의 Type을 지정할 수 있다


1
2
3
4
5
x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[1,2],[3,4]], dtype=np.float64)
z = y.astype(np.int32) # 형변환
print(x,y,z)
print(x.dtype, y.dtype, z.dtype)


[[1. 2.]
 [3. 4.]] [[1. 2.]
 [3. 4.]] [[1 2]
 [3 4]]
float64 float64 int32

다른 배열의 dtype으로 변형 시킬 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
print(x+y)
print(np.add(x,y))
print(np.subtract(x,y))
print(np.multiply(x,y))
print(np.divide(x,y))
v = np.array([9, 10])
w = np.array([11, 12])
print(v.dot(w))
print(np.dot(v,w))
print(x)
print(v)
print(x.dot(v))
print(np.dot(x,v))


[[2. 4.]
 [6. 8.]]
[[2. 4.]
 [6. 8.]]
[[0. 0.]
 [0. 0.]]
[[ 1.  4.]
 [ 9. 16.]]
[[1. 1.]
 [1. 1.]]
219
219
[[1. 2.]
 [3. 4.]]
[ 9 10]
[29. 67.]
[29. 67.]
np.add(x)x+y
np.subtract(x)x-y
np.multiply(x)x*y
np.divide(x)x/y
np.dot(x)x,y의 백터의 내적 연산



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#내장함수
print(x)
print(np.sum(x))
print(np.sum(x, axis=0)) #열에 대한 합
print(np.sum(x, axis=1)) #행에 대한 합
print(np.argmax(x))
print(np.cumsum(x))
print(np.cumprod(x))

names = np.array(["tom","james","tom","oscar"])
names2 = np.array(["tom","page","john"])
print(np.unique(names)) #중복없이
print(np.intersect1d(names, names2)) #교집합
print(np.intersect1d(names, names2, assume_unique=True))
# assume_unique=True -> 중복을 허용하는 옵션
print(np.union1d(names, names2)) #합집합


[[1. 2.]
 [3. 4.]]
10.0
[4. 6.]
[3. 7.]
3
[ 1.  3.  6. 10.]
[ 1.  2.  6. 24.]
['james' 'oscar' 'tom']
['tom']
['tom' 'tom']
['james' 'john' 'oscar' 'page' 'tom']

Numpy 내장함수.

np.sum(x)x집합의 모든 원소의 합
np.sum(x, axis=0)열에 대한 합
np.sum(x, axis=1)행에 대한 합
np.argmax(x)x집합의 원소중 가장 큰 값
np.cumsum(x)누적 합계
np.cumprod(x)누적 곱
np.unique(x)중복없이 만듬
np.intersect1d(names, names2)교집합
np.intersect1d(names, names2, assume_unique=True)교집합(중복 허용)
np.union1d(names, names2)합집합



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#Transpose
print(x)
print(x.T)

print(x.transpose())
print(x.swapaxes(0,1))

arr = np.arange(1,16).reshape((3,5))
print(arr)
print(arr.T)

print(np.dot(arr.T, arr))

print(v)
print(v.T)


[[1. 2.]
 [3. 4.]]
[[1. 3.]
 [2. 4.]]
[[1. 3.]
 [2. 4.]]
[[1. 3.]
 [2. 4.]]
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]
 [11 12 13 14 15]]
[[ 1  6 11]
 [ 2  7 12]
 [ 3  8 13]
 [ 4  9 14]
 [ 5 10 15]]
[[158 176 194 212 230]
 [176 197 218 239 260]
 [194 218 242 266 290]
 [212 239 266 293 320]
 [230 260 290 320 350]]
[ 9 10]
[ 9 10]

Transpose: 행렬을 전치 시키는 방법

1
2
3
4
5
6
7
8
9
10
print(x)
np.save("test1", x) # 바이너리 데이터로 저장
np.savez("test2", x) 
np.savetxt("text3", x) # 텍스트 파일로 저장

mydatas = np.load("test1.npy")
print(mydatas)

mydatas2 = np.loadtxt("text3")
print(mydatas2)


[[1. 2.]
 [3. 4.]]
[[1. 2.]
 [3. 4.]]
[[1. 2.]
 [3. 4.]]

선언한 Vector를 텍스트 파일로 저장하고 불러오는 방법이다.

1
2
3
4
5
6
7
8
aa = np.eye(3) #단위행렬
print(aa)

bb = np.c_[aa, aa[2]]
print(bb)

cc = np.r_[aa, [aa[2]]]
print(cc)


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

c_, r_을 활용하여 행/열을 추가한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
x = np.array([1,2,3])
y = np.array([4,5,6])
conditionData = np.array([True, False, True])
result = np.where(conditionData, x, y)
print(result)

print("\n")
aa = np.where(x>=2) #인덱스 출력
print(aa)
print(x[aa])

print(np.where(x>=2),"T","F")
print(np.where(x>=2),x,x+100)

print("\n")
testData = np.random.randn(4,4)
print(testData)
print(np.where(testData > 0, 2, testData))
print(np.where(testData > 0, testData, testData * -1))


[1 5 3]


(array([1, 2], dtype=int64),)
[2 3]
(array([1, 2], dtype=int64),) T F
(array([1, 2], dtype=int64),) [1 2 3] [101 102 103]


[[-0.37447169  0.27519832 -0.96075461  0.37692697]
 [ 0.03343893  0.68056724 -1.56349669 -0.56669762]
 [-0.24214951  1.51439128 -0.3330574   0.04736482]
 [ 1.46274045  1.53502913  0.56644004  0.14926509]]
[[-0.37447169  2.         -0.96075461  2.        ]
 [ 2.          2.         -1.56349669 -0.56669762]
 [-0.24214951  2.         -0.3330574   2.        ]
 [ 2.          2.          2.          2.        ]]
[[0.37447169 0.27519832 0.96075461 0.37692697]
 [0.03343893 0.68056724 1.56349669 0.56669762]
 [0.24214951 1.51439128 0.3330574  0.04736482]
 [1.46274045 1.53502913 0.56644004 0.14926509]]

Where를 사용하여 원하는 정보를 Filtering하여 가져올 수 있다.

참조: 원본코드
코드에 문제가 있거나 궁금한 점이 있으면 wjddyd66@naver.com으로 Mail을 남겨주세요.

Leave a comment