BACK END/Python Library

[NumPy] numpy 정리

circle kim 2021. 2. 23. 16:24

numpy 모듈

: 데이터 분석 시 과학적 계산을 위한 핵심 라이브러리
: ndarray 지원. 다차원 배열 객체.

: 선형대수 계산
: 파이썬 데이터 분석 핵심.

함수명 기능
import numpy as np
np.sum(x)
np.mean(x) 평균
np.var(x) 분산
np.std(x) 표준편차(√분산)
np.array(x, dtype=) np.narray타입으로 변경. dtype : 내부 요소 타입 변경가능.
type(x) 타입 반환
x.dtype 데이터 타입 반환
x.shape 행 열 수 반환 (튜플)
x.ndim 차원 수 반환
x.size 원소 수 반환
np.zeros((행 수, 열 수)) 0으로 채워진 (행 X 열)의 배열 생성
np.ones((행 수, 열 수)) 1으로 채워진 (행 X 열)의 배열 생성
np.full((행 수, 열 수), x) x로 채워진 (행 X 열)의 배열 생성
np.eye(x) x행 x열의 단위 행열 생성. (대각선으로 1 채워진 행열)
 np.random.rand(x) x개의 균등분포 난수 생성.
 np.random.randn(x) x개의 정규분포 난수 생성.(평균 : 0, 표준편차 : 1)
 np.random.randint(x, size(차원, 행, 열) 0 ~ x-1까지 난수를 가진 행 X 열 X 차원의 배열 생성
x.copy() 배열을 복사. (복사된 배열 수정 시 원본배열 변경사항 없음)
np.arange(x, y) x에서 y-1까지 array 생성.
x.reshape(행, 열) 배열을 행 수 X 열 수로 변경.
x.astype(y) x를 y타입으로 변경
np.add(x, y) 배열 x, y 더하기
np.substract(x, y) 배열 x, y 빼기
np.multiply(x, y) 배열 x, y 곱하기
np.div(x, y) 배열 x, y 나누기
np.dot(x, y) x배열 y배열 내적
np.cumsum(x) 누적 합
np.cumprod(x) 누적 곱
 np.unique(x) 배열의 중복된 값 제거
 np.instersect1d(x, y, assume_unique=True) x와 y의 교집합 (assume_unique=True : 중복허용)
 np.union1d(x, y) x와 y의 합집합
x.transpose()
행렬 위치 변경(전치)
x.T 전치
x.swapaxes(a, b) a차원과 b차원 위치 변경(전치)
np.c_[x, y] x 배열에 y 열 추가
np.r_[x, y] x 배열에 y 행 추가
np.append(x, y) x 배열에 y 열 추가
np.insert(x, a, y) x 배열에 a번째에 y 열에  추가
np.insert(x, a, y, axis=1) x 배열에 a번째에 y 행에  추가
np.delete(x, a) x배열에서 a 열 삭제
np.delete(x, a, axis=1) x배열에서 a 행 삭제
np.where(조건배열, x, y) 각 배열 index마다 조건이 True면 x값 출력, False면 y값 출력
np.concatenate([x, y])  x, y배열 결합
y1, y2, ... = np.split(x, n) x배열을 n개로 나눠 n개의 배열 리턴
y1, y2, ... = np.hsplit(x, n) x배열을 열로 나눠 n개의 배열 리턴
y1, y2, ... = np.vsplit(x, n) x배열을 행으로 나눠 n개의 배열 리턴
import random
random.randint(n) 0에서 n-1까지의 난수 1개 복원 추출
random.randint(start, end) start에서 end-1까지 난수 1개의 복원 추출
random.rand(n) 0에서 1 사이의 표준정규분포를 따르는 n개의 난수 추출.
random.rand(m, n) 0에서 1 사이의 표준정규분포를 따르는 m x n의 난수 추출.
random.randn(n) 평균 0, 표준편차 1인 가우시안 정규분포의 n개 난수 추출.
random.randn(m, n) 평균 0, 표준편차 1인 가우시안 정규분포의 m x n개 난수 추출.
random.sample(리스트, k=n) 리스트에서 n개의 난수 비복원 추출
np.random.choice(배열, n) 배열에서 n개의 복원 추출
np.random.choice(배열, n, replace=False) 배열에서 n개의 비복원 추출
np.random.choice(배열, n, replace=False, p=[0.1, 0.9]) 배열에서 n개의 비복원 추출. p는 n개의 원소를 가지고 총합이 1이어야함. p의 값에 따른 가중치 부여

 * numpy1

 - 기본 통계 함수를 직접 작성 후 함수와 결과 비교

grades = [1, 3, -2, 4]

print(grades)

def show_grades(grades):
  for g in grades:
    print(g, end = ' ')

show_grades(grades)
[1, 3, -2, 4]
1 3 -2 4 
grades = [1, 3, -2, 4]
def grades_sum(grades): # 합
  tot = 0
  for g in grades:
    tot += 9
  return tot

def grades_ave(grades): # 평균
  tot = greads_sum(grades)
  ave = tot / len(grades)
  return ave

def greades_variance(grades): # 분산
  ave = grades_ave(grades)
  vari = 0
  for su in grades:
    vari += (su - ave) ** 2
  return vari / len(grades)
  #return vari / (len(grades) - 1)

def grades_std(grades):  # 표준편차
    return greades_variance(grades) ** 0.5

print('합은 ', grades_sum(grades))
print('평균은 ', grades_ave(grades))
print('분산은 ', greades_variance(grades))
print('표준편차는 ', greades_variance(grades))

 

 - numpy 함수를 사용

import numpy as np
print('합은 ', np.sum(grades))
print('평균은 ', np.mean(grades))
print('분산은 ', np.var(grades))
print('표준편차는 ', np.std(grades))
합은  36
평균은  9.0
분산은  61.5
표준편차는  61.5

합은  6
평균은  1.5
분산은  5.25
표준편차는  2.29128784747792
함수명 기능
import numpy as np  
np.sum(x)
np.mean(x) 평균
np.var(x) 분산
np.std(x) 표준편차(√분산)

 

 * numpy2

import numpy as np

ss = ['tom', 'james', 'oscar']
print(ss, ' ', type(ss))
# ['tom', 'james', 'oscar']   <class 'list'>

ss2 = np.array(ss)
print(ss, ' ', type(ss2))
# ['tom', 'james', 'oscar']   <class 'numpy.ndarray'>
# 메모리 비교
li = list(range(1,10))
print(li)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

print(li[0], li[1], ' ', id(li[0]), id(li[1]))
# 1 2   10914496 10914528

print(li * 10)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print('-' * 10)
# ----------

# li 각 요소와 10 곱하기
for l in li:
    print(l * 10, end=' ')
# 10 20 30 40 50 60 70 80 90 
# ndarray
num_arr = np.array(li)
print(id(num_arr), id(num_arr[0]), id(num_arr[1]))
# 140361351910064 140361354499656 140361354499656

print(num_arr * 10)
# [10 20 30 40 50 60 70 80 90]

 => list의 각 요소는 각각 memory를 할당받아 메모리 소모가 크다.

      * 연산 시 전체 값을 반복한다.

 

 => array의 각 요소는 동일한 메모리를 할당 받아 메모리 소모가 작다.

      * 연산 시 각 요소에 연산된다.

 

# 배열의 속성은 모두 동일. 우선순위에 따라 data type이 변경됨.
a = np.array([1, 2, 3.2]) # 우선순위 int -> float -> complex -> str
a = np.array([1, 2, 3], dtype='float32') 

print(a, type(a), a.dtype, a.shape, a.ndim, a.size)
# [1. 2. 3.] <class 'numpy.ndarray'> float32 (3,) 1 3

print(a[0]) # 1.0

a[0] = 8
print(a[0]) # 8.0

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

print(b[0,0]) # 1
print(b[0], b[[0]]) # 1차원, 2차원
# [1 2 4] [[1 2 4]]

 => 배열의 속성은 모두 동일. 우선순위에 따라 data type이 변경됨.

      우선순위 int -> float -> complex -> str

함수명 기능
np.array(x, dtype=) np.narray타입으로 변경. dtype : 내부 요소 타입 변경가능.
type(x) 타입 반환
x.dtype 데이터 타입 반환
x.shape 행 열 수 반환 (튜플)
x.ndim 차원 수 반환
x.size 원소 수 반환

 

c = np.zeros((2, 2)) # 2행 2열의 0으로 채워진 배열 생성
print(c)
[[0. 0.]
 [0. 0.]]

d = np.ones((2, 2)) # 2행 2열의 1으로 채워진 배열 생성
print(d)
[[1. 1.]
 [1. 1.]]

e = np.full((2, 2), 7) # 2행 2열의 7으로 채워진 배열 생성
print(e)
[[7 7]
 [7 7]]

f = np.eye(3) # 3행 3열의 단위행렬
print(f)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
함수명 기능
np.zeros((행 수, 열 수)) 0으로 채워진 (행 X 열)의 배열 생성
np.ones((행 수, 열 수)) 1으로 채워진 (행 X 열)의 배열 생성
np.full((행 수, 열 수), x) x로 채워진 (행 X 열)의 배열 생성
np.eye(x) x행 x열의 단위 행열 생성. (대각선으로 1 채워진 행열)

 

print(np.random.rand(5)) # 균등분포
[0.20323807 0.81989097 0.84142846 0.46991121 0.21930122]

print(np.mean(np.random.rand(5)))
0.4230689697221274

print(np.random.randn(5)) # 정규분포
[-1.52232689 -0.31403199 -0.81191411  1.16482644 -0.23161658]

print(np.mean(np.random.randn(5)))
0.6515764623112837

x1 = np.random.randint(10, size=6)
[8 3 5 4 3 7]

x2 = np.random.randint(10, size=(3,4))
[[8 9 0 6]
 [5 9 0 2]
 [0 4 7 0]]

x3 = np.random.randint(10, size=(3,4,4))
print(x1)
[[[8 1 9 1]
  [4 9 3 7]
  [8 8 4 0]
  [7 9 8 1]]

print(x2)
 [[0 9 1 5]
  [7 8 4 0]
  [4 6 4 2]
  [9 8 9 2]]

print(x3)
 [[3 5 9 5]
  [7 3 5 4]
  [1 0 5 7]
  [2 2 2 2]]]

print(x3.ndim, x3.shape)
3 (3, 4, 4)
함수명 기능
 np.random.rand(x) x개의 균등분포 난수 생성.
 np.random.randn(x) x개의 정규분포 난수 생성.(평균 : 0, 표준편차 : 1)
 np.random.randint(x, size(차원, 행, 열) 0 ~ x-1까지 난수를 가진 행 X 열 X 차원의 배열 생성

 

# 슬라이싱
a = np.array([1,2,3,4,5])
print(a, a[1], a[1:5:2], a[1:], a[1:5])
[1 2 3 4 5] 2 [2 4] [2 3 4 5] [2 3 4 5]

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

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

print(a[1:])
[[ 5  6  7  8]
 [ 9 10 11 12]]

 => a[x:y:z] : index x에서 y-1까지 z간격의 슬라이싱

 => a    =    a[:]

 => a[x][y] : x행, y열의 값

 

print(a[1:, 0:2])
[[ 5  6]
 [ 9 10]]

print(a)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

b = a[:2, 1:3] # 서브 배열
print(b)
[[2 3]
 [6 7]]

b[0,0] = 77
print(b)
[[77  3]
 [ 6  7]]

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

bb = aa[1:3]
print(bb)
[2 3]

bb[0] = 100
print(aa)
[  1 100   3]

print(bb)
[100   3]

aa[1] = 50
print(aa)
[ 1 50  3]

print(bb)
[50  3]

 => a[x:y, b:c] : index x에서 y-1 각 행에서 index b에서 c-1까지의 열 데이터.

 => 서브배열을 수정하면 원본의 데이터도 수정된다.

 

cc = aa[1:3].copy() # 배열 복사본 작성
print(cc)
[50  3]

cc[0] = 99
print(cc)
[99  3]

print(aa)
[ 1 50  3]

 => copy()를 이용하여 복사 시 서브배열을 수정하여도 원본 데이터는 변경 되지않는다.

함수명 기능
x.copy() 배열을 복사. (복사된 배열 수정 시 원본배열 변경사항 없음)

 

 * numpy3

# 배열 연산
import numpy as np

x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.arange(5, 9).reshape((2,2)) # 배열 변경
y = y.astype(np.float32) # 타입 변경
print(x)
[[1. 2.]
 [3. 4.]]

print(y)
[[5. 6.]
 [7. 8.]]
함수명 기능
np.arange(x, y) x에서 y-1까지 array 생성.
x.reshape(행, 열) 배열을 행 수 X 열 수로 변경.
x.astype(y) x를 y타입으로 변경

 

print(x + y)
[[ 6.  8.]
 [10. 12.]]
 
print(np.add(x, y)) # numpy 유니버셜 함수
[[ 6.  8.]
 [10. 12.]]

print(x - y) # np.substract()
[[-4. -4.]
 [-4. -4.]]

print(x * y) # np.multiply()
[[ 5. 12.]
 [21. 32.]]

print(x / y) # np.divid()
[[0.2        0.33333333]
 [0.42857143 0.5       ]]
함수명 기능
np.add(x, y) 배열 x, y 더하기
np.substract(x, y) 배열 x, y 빼기
np.multiply(x, y) 배열 x, y 곱하기
np.div(x, y) 배열 x, y 나누기

 

# python 함수보다 numpy 지원 함수가 계산 속도가 빠름

big_arr = np.random.rand(1000000) # 난수 발생

%timeit sum(big_arr) # python 함수

# 10 loops, best of 3: 155 ms per loop
%timeit np.sum(big_arr) # numpy 함수
# The slowest run took 23.08 times longer than the fastest. This could mean that 
# an intermediate result is being cached. 1000 loops, best of 3: 538 µs per loop

 

# 내적
v = np.array([9, 10])
w = np.array([11, 12])
print(v * w)
[ 99 120]


print(v.dot(w))    # 219
print(np.dot(v,w)) # 219

print(x)
[[1. 2.]
 [3. 4.]]
 
print(np.dot(x, y))
[[19. 22.]
 [43. 50.]]
print(sum(x), np.sum(x))
[4. 6.] 10.0

print(np.cumsum(x)) # 누적 합
[ 1.  3.  6. 10.]

print(np.cumprod(x)) # 누적 곱
[ 1.  2.  6. 24.]

names = np.array(['tom', 'james', 'tom', 'oscar'])
names2 = np.array(['tom', 'page', 'john'])
print(np.unique(names)) # 중복 제거
['james' 'oscar' 'tom']

print(np.intersect1d(names, names2)) # 중복 제거
['tom']

print(np.intersect1d(names, names2, assume_unique=True)) # 중복 허용
['tom' 'tom']

print(np.union1d(names, names2))
['james' 'john' 'oscar' 'page' 'tom']
함수명 기능
np.dot(x, y) x배열 y배열 내적
np.cumsum(x) 누적 합
np.cumprod(x) 누적 곱
 np.unique(x) 배열의 중복된 값 제거
 np.instersect1d(x, y, assume_unique=True) x와 y의 교집합 (assume_unique=True : 중복허용)
 np.union1d(x, y) x와 y의 합집합

 

# 전치 : 행렬 위치 변경
print(x)
[[1. 2.]
 [3. 4.]]
 
print(x.T)
[[1. 3.]
 [2. 4.]]

print(x.transpose())
[[1. 3.]
 [2. 4.]]

print(x.swapaxes(0, 1))
[[1. 3.]
 [2. 4.]]
함수명 기능
x.transpose()
행렬 위치 변경(전치)
x.T 전치
x.swapaxes(a, b) a차원과 b차원 위치 변경(전치)

 

# Broadcasting : 크기가 다른 배열 간의 연산.
x = np.arange(1, 10).reshape(3, 3)
y = np.array([1, 0 , 1])
print(x)
[[1 2 3]
 [4 5 6]
 [7 8 9]]

print(y)
[1 0 1]

print(x + y)
[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]]

 

# 배열에 행, 또는 열 추가
aa = np.eye(3)
print(aa)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

bb = np.c_[aa, aa[2]] # 2 열과 동일한 열 추가
print(bb)
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 1.]]

cc = np.r_[aa, [aa[2]]] # 2 행과 동일한 행 추가
print(cc)
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]
 [0. 0. 1.]]

a = np.array([1,2,3])
b = np.append(a, [4, 5]) # 열 방향 추가
print(b)
[1 2 3 4 5]

c = np.insert(a, 0, [6, 7]) # axis = 0, 열 방향 삽입
print(c)
[6 7 1 2 3]

d = np.delete(a, 1)
print(d)
[1 3]

# 2차원도 가능.. # axis = 0 열 방향,  axis = 1 행 방향
함수명 기능
np.c_[x, y] x 배열에 y 열 추가
np.r_[x, y] x 배열에 y 행 추가
np.append(x, y) x 배열에 y 열 추가
np.insert(x, a, y) x 배열에 a번째에 y 열에  추가
np.insert(x, a, y, axis=1) x 배열에 a번째에 y 행에  추가
np.delete(x, a) x배열에서 a 열 삭제
np.delete(x, a, axis=1) x배열에서 a 행 삭제

 

# where 조건 연산
x = np.array([1,2,3])
y = np.array([4,5,6])
conditionData = np.array([True, False, True])
print(np.where(conditionData, x, y))
[1 5 3]

aa = np.where(x >= 2)
print(aa) #(array([1, 2]),)

print(x[aa])
[2 3]

print(np.where(x >= 2, 'T', 'F'))
['F' 'T' 'T']

print(np.where(x >= 2, x, x + 200))
[201   2   3]
함수명 기능
np.where(조건배열, x, y) 각 배열 index마다 조건이 True면 x값 출력, False면 y값 출력

 

# 배열 결합
kbs = np.concatenate([x, y])
print(kbs)
[1 2 3 4 5 6]

x1, x2 = np.split(kbs, 2)
print(x1)
[1 2 3]

print(x2)
[4 5 6]

a = np.arange(1, 17).reshape((4, 4))
print(a)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]
 [13 14 15 16]]

x1, x2 = np.hsplit(a, 2)
print(x1)
[[ 1  2]
 [ 5  6]
 [ 9 10]
 [13 14]]

print(x2)
[[ 3  4]
 [ 7  8]
 [11 12]
 [15 16]]

print(np.vsplit(a, 2))
[array([[1, 2, 3, 4],
       [5, 6, 7, 8]]), array([[ 9, 10, 11, 12],
       [13, 14, 15, 16]])]
함수명 기능
np.concatenate([x, y])  x, y배열 결합
y1, y2, ... = np.split(x, n) x배열을 n개로 나눠 n개의 배열 리턴
y1, y2, ... = np.hsplit(x, n) x배열을 열로 나눠 n개의 배열 리턴
y1, y2, ... = np.vsplit(x, n) x배열을 행으로 나눠 n개의 배열 리턴

 

 * numpy4

# 복원/ 비복원 추출 - 데이터 집합으로 부터 무작위로 일부 자료 선택
# 복원 - 추출된 데이터가 다시 추출가능한 추출.
import numpy as np
import random

li = np.array([1,2,3,4,5,6,7])
# 복원 추출
for _ in range(5): # 5개의 난수 추출(복원)
    print(li[random.randint(0, len(li) - 1)], end = ' ')
6 1 6 5 2 

# 비복원 추출
print(random.sample(list(li), k = 5)) # 5개의 난수 추출(비복원). list 타입만 가능. list 출력.
[3, 7, 2, 5, 6]

print(random.sample(range(1, 46), k = 6)) # 로또 번호 추출
[40, 29, 15, 24, 38, 7]
# choice
print(list(np.random.choice(range(1, 46), 6))) # 복원 추출. 1 ~ 46 까지 6개 추출.
[16, 24, 35, 34, 26, 35]

print(list(np.random.choice(range(1, 46), 6, replace=True))) # 복원 추출.
[1, 33, 13, 15, 42, 35]

print(list(np.random.choice(range(1, 46), 6, replace=False))) # 비복원 추출.
[39, 4, 1, 11, 27, 28]

# 가중치를 부여한 랜덤 추출
ar = 'air book cat desk, egg, fox, god'
ar = ar.split(' ') # ' '을 기준으로 분해.
print(ar)
['air', 'book', 'cat', 'desk,', 'egg,', 'fox,', 'god']

print(np.random.choice(ar, 3, p = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.4]))
['god' 'desk,' 'god']
# p의 합은 1로 클 수록 추출될 확률이 증가한다.
함수명 기능
import random  
random.randint(n) 0에서 n-1까지의 난수 1개 복원 추출
random.randint(start, end) start에서 end-1까지 난수 1개의 복원 추출
random.rand(n) 0에서 1 사이의 표준정규분포를 따르는 n개의 난수 추출.
random.rand(m, n) 0에서 1 사이의 표준정규분포를 따르는 m x n의 난수 추출.
random.randn(n) 평균 0, 표준편차 1인 가우시안 정규분포의 n개 난수 추출.
random.randn(m, n) 평균 0, 표준편차 1인 가우시안 정규분포의 m x n개 난수 추출.
random.sample(리스트, k=n) 리스트에서 n개의 난수 비복원 추출
np.random.choice(배열, n) 배열에서 n개의 복원 추출
np.random.choice(배열, n, replace=False) 배열에서 n개의 비복원 추출
np.random.choice(배열, n, replace=False, p=[0.1, 0.9]) 배열에서 n개의 비복원 추출. p는 n개의 원소를 가지고 총합이 1이어야함. p의 값에 따른 가중치 부여