Numpy

Numerical Python의 약자, 산술 계산용 라이브러리

  • ndarray 다차원 배열객체 -> 빠르고 효율적인 메모리 사용과 유연한 브로드캐스팅이 가능하다.
  • 디스크로부터 배열 기반의 데이터를 읽거나 쓸 수 있는 도구
  • C, C++, 포트란 등으로 쓰여진 코드를 통합하는 도구
  • 다차원적인 배열 객체, 다양한 파생 객체(마스크 된 배열 및 행렬 등)에 대한 루틴들, 수학적 논리적 형상 조작, 정렬, 선택, I/O, 기본 선형대수 계산, 푸리에 변환, 난수 생성기, 기초 통계 연산, 무작위 시뮬레이션 등 다양한 작업을 수행할 수 있는 라이브러리다.
import numpy as np

n=100000
numpy_arr = np.arange(n)
python_list = list(range(n))

 

NumPy("넘파이"라 읽는다)는 행렬이나 일반적으로 대규모 다차원 배열을 쉽게 처리할 수 있도록 지원하는 파이썬의 라이브러리이다. NumPy는 데이터 구조 외에도 수치 계산을 위해 효율적으로 구현된 기능을 제공한다.

위키백과

 


Python NumPy ndarray

NumPy에서 제공하는 핵심 기능 중 하나. N차원의 배열 객체 자료구조.
대규모의 데이터 집합을 담을 수 있는 자료구조다.

import numpy as np
print(np.__version__) # 버전 확인

 

 

ndarray 타입을 검색하거나 슬라이싱할 때 참조만 할당하므로,

변경을 방지하기 위해서는 새로 만들어 사용하는 것이 좋다. .copy 메소드가 필요함.

import numpy as np
A = [1,2,3,4]
a = np.array(A)
s = a[:2]
print('A의 출력입니다.%a' %a) # A의 출력입니다.array([1, 2, 3, 4])
print('s의 출력입니다.%s' %s) # s의 출력입니다.[1 2]
ss = a[:2].copy()
print(ss.size) # 2
ss[0]=99
print(a) # [1 2 3 4]
print(s) # [1 2]
print(ss) # [99 2]

 

 

벡터화 하여 계산하는 것이 큰 특징이다.
for문을 사용하지 않고도 데이터를 일괄 처리해 줌

arr = np.array([[1,2,3],[4,5,6]])
arr
# array([[1, 2, 3],
#       [4, 5, 6]])
arr = np.array([[1, 2, 3], [4, 5, 6]])
arr + arr
# array([[ 2,  4,  6],
#        [ 8, 10, 12]])
arr = np.array([[1,2,3],[4,5,6]])
arr/arr
# array([[1., 1., 1.],
#       [1., 1., 1.]])

 


list vs numpy array

list()
numpy array()
data = [1,2,3,4,5,6,7]
type(data) # list
x = np.array(data)
type(x) # numpy.ndarray
파이썬 내장 함수
파이썬 외부 함수
numpy 패키지 import 해야 함
루프 가능
벡터화하여 계산한다.
for문 없이 데이터 일괄처리
코드 간결해서 버그 확률 줄어듬
표준수학 표기법과 유사
L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(2 * L)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
x = np.array(data)
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2 * x
# array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
덧셈 시 이어붙임 concatenate
자연수 곱셈 가능 (원소 복사 의미)
덧셈 시 항목 간 덧셈 수행,
다른 사칙연산도 마찬가지로 수행됨.
실수에 대한 사칙 연산과정도 원소 전체 값에 대해 수행 가능.
선언조건 : 숫자형, 문자열 등 모든 자료 타입 보존
여러가지 자료형 허용
모든 원소가 같은 자료형이어야 한다.
숫자형과 문자열이 섞이면 모두 문자열로 전환
한가지 자료형만 허용
동적 할당
크기가 계속 변할 수 있다.
정적 할당
고정된 갯수와 크기를 갖는다.
사이즈가 변화하면 기존의 array를 삭제, 새로운 array를 생성해야 함
데이터 주소값을 저장한 것이다.
C 배열과 유사하게
연속된 주소를 가지고 있다.
2차원 이상의 배열에서 내부 배열 원소 개수 달라도 됨
2차원 이상의 배열에서 내부 배열 내 원소개수가 모두 같아야 함
append, remove, extend 등 지원
mean, argmax, round 등 지원
연산 속도는 좀 더 많이 걸림.
데이터가 많아질수록 차이가 커짐
C로 구현한 내부 반복문 사용
연산 최적화 더 잘 되어 있음
수학적 모델에서 동작시킬 때 빠름

Python NumPy Broadcasting

브로드캐스팅이라는 용어는 NumPy가 산술 연산 중에 다양한 모양의 배열을 처리하는 방법을 설명합니다. 특정 제약 조건에 따라 더 작은 배열은 더 큰 배열에서 "브로드캐스팅"되어 호환되는 모양을 갖춥니다. 브로드캐스팅은 파이썬 대신 C에서 루핑이 발생하도록 배열 연산을 벡터화하는 수단을 제공합니다. 불필요한 데이터 복사본을 만들지 않고 이 작업을 수행하며 일반적으로 효율적인 알고리즘 구현으로 이어집니다. 그러나 브로드캐스팅은 계산 속도를 늦추는 비효율적인 메모리 사용으로 이어지는 경우도 있습니다.

  • 다른 모양의 배열 간의 산술 연산을 수행할 수 있도록 해 주는 NumPy 기능 중 하나
  • 브로드캐스팅이 가능하려면 연산을 수행하는 축을 제외한 나머지 축의 shape가 일치하거나 둘 중 하나의 길이가 1이어야 함
  • 어떤 조건을 만족했을 때 다른 배열들 간의 연산이 가능해지도록 배열을 자동적으로 변환한다.
import numpy as np
a = np.array([1.0, 2.0, 3.0])
b = np.array([2.0, 2.0, 2.0])
a * b
# array([2.,  4.,  6.])
 
import numpy as np
a = np.array([1.0, 2.0, 3.0])
b = 2.0
a * b
# array([2.,  4.,  6.])

위 그림 및 코드와 같이 b에 할당된 정수 스칼라 인자가 a에 할당된 배열의 모든 원소에 각각 적용된다.

import numpy as np
arr = np.array([[1,2,3],[4,5,6]])
arr * 3
# array([[ 3,  6,  9],
#       [12, 15, 18]])
arr = np.array([[1,2,3],[4,5,6]])
10 - arr
# array([[9, 8, 7],
#       [6, 5, 4]])
arr = np.array([[1,2,3],[4,5,6]])
arr / 3
# array([[0.33333333, 0.66666667, 1.        ],
#       [1.33333333, 1.66666667, 2.
arr5 = np.array([1, 2, 3]) 
arr6 = np.array([2, 4, 6]) 
arr5 + arr6
# array([3, 6, 9]) # list끼리 합치면 결과는 [1, 2, 3, 2, 4, 6] 이렇게 나온다.
arr5 = np.array([1, 2, 3]+[2, 4, 6]) 
arr5
# array([1, 2, 3, 2, 4, 6])
arr7 = np.array([2, 4, 6]+[1, 2, 3]) 
arr7
# array([2, 4, 6, 1, 2, 3])
arr4 = np.array([[100],[200]])
arr4
# array([[100],
#       [200]])

Python NumPy ndarray asarray()

리스트를 numpy.ndarray 타입으로 변환해 준다.

a = [1, 2, 3, 4, 5]
type(a)
# list

a = np.asarray(a)
type(a)
# numpy.ndarray

 

Python NumPy ndarray attributes

1. dtype

ndarray에는 같은 자료형만 배열해야 한다. dtype은 배열의 원소 자료형을 의미한다.

  • dtype으로 데이터 타입을 명시하지 않은 경우 자료형을 추정하여 저장한다.
  • dtype이 있어서 포트란 같은 저수준 언어(기계어에 더 가까운)로 작성된 코드와 쉽게 연동이 가능

2. size

배열에 있는 원소의 전체 갯수

arr = np.array([[1,2,3],[4,5,6]])
arr.size
# 6

3. ndim

배열 차원의 갯수

arr = np.array([[1,2,3],[4,5,6]])
arr.ndim
# 2

3.1. 0 차원

import numpy as np
a = np.array(10)
print(a) # 10
print(a.ndim) # 0

3.2. 1 차원

a = np.array([1,2,3])
print(a) # [1 2 3]
print(a.ndim) # 1

3.3. 2 차원

a = np.array([[1,2],[3,4]])
print(a)
# [[1, 2]
# [3, 4]]
print(a.ndim) # 2

3.4. 3 차원 이상은 복잡해짐

a = np.array([[[[1,2],[3,4]]]])
print(a)
# [[[1, 2]
# [3, 4]]]
print(a.ndim) # 4
print(a.shape) # (1, 1, 2, 2)

4. shape

  • 배열 각 차원의 크기
  • 튜플 형태로 리턴
arr = np.array([[1,2,3],[4,5,6]])
arr.shape
# (2, 3)
 

Python NumPy ndarray Create ndarray np.arange()

1. array 함수

  • np.arange(숫자) : 0부터 숫자-1까지 숫자 갯수의 원소 배열이 생성된다.
arr2 = np.arange(20)
arr2
# array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

 

2. 배열생성함수

  • 0 할당 : 공간이 비어 있다.
  • empty : 0에 가깝지만 비어 있지 않음.
  • None : None이 할당된 거. 할당되었다는 건 메모리가 있다는 거
np.zeros(5)
# array([0., 0., 0., 0., 0.])
np.ones((3,3))
# array([[1., 1., 1.],
#       [1., 1., 1.],
#       [1., 1., 1.]])
np.full((4),5)
# array([5, 5, 5, 5])
np.empty((2,3),dtype=np.float32)
# array([[1.4e-43, 0.0e+00, 2.8e-43],
#       [0.0e+00, 4.2e-43, 0.0e+00]], dtype=float32)
np.arange(-3,3)
# array([-3, -2, -1,  0,  1,  2])
np.arange(3, 50, 3)
# array([ 3,  6,  9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48])
np.linspace(0,1,6)
# array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])
# 0부터 1까지 6등분으로 잘게 쪼갠다. 그림 그릴 때 씀

 

 

3. 배열결합함수

  • hstack(horizontal stack), concatenate(axis=0)
  • vstack(vertical stack), concatenate(axis=1)
  • np.column_stack([a,b])
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
np.hstack([a, b])
# array([1, 2, 3, 4, 5, 6])
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
np.concatenate((a, b),axis=0) # axis=0은 행으로 인식
# array([1, 2, 3, 4, 5, 6])
a = ([1, 2, 3])
b = ([4, 5, 6])
np.hstack([a, b])
# array([1, 2, 3, 4, 5, 6])
a = ([1, 2, 3])
b = ([4, 5, 6])
np.concatenate((a, b), axis=0)
# array([1, 2, 3, 4, 5, 6])
a = np.array([1,2,3])
b = np.array([4,5,6])
np.vstack([a,b])
# array([[1, 2, 3],
#       [4, 5, 6]])
a = ([1,2,3])
b = ([4,5,6])

np.concatenate((a,b), axis=1) // #1D vector는 안됨
# AxisError: axis 1 is out of bounds for array of dimension 1
c = np.array([[0,1,2],[3,4,5]])
d = np.array([[6,7,8],[9,10,11]])

np.concatenate((c,d),axis=1)
# array([[ 0,  1,  2,  6,  7,  8],
#       [ 3,  4,  5,  9, 10, 11]])
a = np.array([1,2,3])
b = np.array([4,5,6])

np.column_stack([a,b])
# array([[1, 4],
#       [2, 5],
#       [3, 6]])

Python NumPy ndarray random

난수 생성

  • 랜덤 모듈은 난수를 생성시키는 모듈임.
  • 모듈 안에 여러 함수가 존재한다.
data = [1,2,3,4,5,6,7]
np.random.choice(data,3)
# array([6, 6, 2])

 

 

seed

  • 난수 초기값 부여-> 재현 가능성(Reporducibility)
np.random.seed(42)
np.random.rand(1000)
np.random.randn(1000) #정규분포

 

 

random module

import random
random.random() # 0 <=리턴값<=1
# 0.8696562645816829

random number 난수, 亂數

① n 진법의 각 자릿수가 1/n의 발생 확률로 얻어지는 무작위 숫자. 예를 들어, 10진수 236에서 첫 번째 자릿수인 2는 10개 숫자 중에서 1/10의 확률로 얻어진 것이고, 3과 6도 마찬가지로 각각 1/10의 확률로 얻어진 것이다.

② 난수표나 일련의 숫자로부터 선택된 여러 개의 자릿수로 구성된 수.

(IT용어사전, 한국정보통신기술협회)

어느 유한개의 수로 조립된 수의 계열로, 거기에는 주기성이 없고, 각각의 수치값은 그 이전에 출현한 수의 배열에 관계 없이 독립으로 정해진다는 성질이 있는 것. 이것에는 이론적인 분포에 따르는 난수(일양 난수, 지수 난수, 프와송 난수, 정규 난수 등)나 경험적으로 구한 난수가 있다. 난수는 시뮬레이션의 경우 등에 큰 역할을 하는 것이며, 난수를 사용하는 경우에 도움이 되도록 미리 준비한 수표를 난수표라 한다.

(전자용어사전, 1995. 3. 1., 월간전자기술 편집위원회)

True Random Number 순수 난수, 참 난수

불규칙적인 자연현상을 숫자로 변환해 난수를 생성한 것이다. 난수는 통신내용을 전송할 때 암호화가 필요한데 이때 사용되는 방법이다. 무작위 숫자를 이용해 도청이 불가능하도록 했다. 그러나 컴퓨터 기술이 발달하면서 인공적인 난수(의사난수) 패턴이 노출되는 문제가 생겼다. 순수난수는 이를 해결하기 위한 방법이다. 단일광자 검출소자는 빛의 최소 단위인 단일광자(single photon)를 검출할 수 있는 초고감도 광학센서이다. 단일광자 움직임을 포착하면 이를 토대로 완전한 무작위수, 즉 순수난수를 만들 수 있다. 양자암호통신을 활용하면 국방이나 행정 · 금융 · 의료 · 사물인터넷(IoT) 산업 분야에서 핵심정보를 안전하게 전송할 수 있게 된다.

(지형 공간정보체계 용어사전, 2016. 1. 3., 이강원, 손호웅)


 

로또 번호 생성기

import numpy as np
def make_lotto(count):
    for i in range(count):
        lotto_num = [] #로또 번호가 담길 리스트형 변수
        for j in range(6): #6번 반복
            lotto_num = np.random.choice(range(1,46),6,replace=False)
            lotto_num.sort() #값 정렬
        print('{}.로또번호:{}'.format(i+1,lotto_num))

count = int(input('로또 번호를 몇개 생성할까요?'))
make_lotto(count)

# 로또 번호를 몇개 생성할까요?5
# 1.로또번호:[20 21 25 29 40 43]
# 2.로또번호:[ 6 15 32 33 37 41]
# 3.로또번호:[ 1  6  8 21 28 45]
# 4.로또번호:[ 2 10 11 30 37 40]
# 5.로또번호:[ 3  4 15 17 28 43]

 

 

넘파이 버전 확인 방법

버전이 다르면 구문이 달라질 수 있다. 알 수 없는 오류가 생기면 체크해 볼 것.

import numpy as np
print(np.__version__) # 넘파이 버전 확인

 

Python NumPy ndarray flatten()

  • 1D vector로 만드는 것, '평평하게' 만들어 주는 것
arr = np.array([[1,2],[3,4]])
arr.flatten()
# array([1, 2, 3, 4])
arr = np.zeros((3,2))
arr
# array([[0., 0.],
#       [0., 0.],
#       [0., 0.]])
arr.flatten()
# array([0., 0., 0., 0., 0., 0.])

 

 

Python NumPy ndarray reshape()

  • 이미 존재하는 배열을 내가 원하는대로 shape을 조정함.
  • Ndarray 타입을 검색하거나 슬라이싱은 "참조만 할당"하므로 변경을 방지하기 위해서는 새로운 ndarray를 생성해야 함
arr = np.arange(12)
arr
# array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
arr.reshape(3, 4) # 주어진 shape의 약수로 이루어진 shape만 가능
# array([[ 0,  1,  2,  3],
#       [ 4,  5,  6,  7],
#       [ 8,  9, 10, 11]])
arr.reshape(4,3)
# array([[ 0,  1,  2],
#       [ 3,  4,  5],
#       [ 6,  7,  8],
#       [ 9, 10, 11]])
arr.reshape(1,12) # == flatten() 1이니까. 
# array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11]])
arr.reshape(12,1)
# array([[ 0],
#       [ 1],
#       [ 2],
#       [ 3],
#       [ 4],
#       [ 5],
#       [ 6],
#       [ 7],
#       [ 8],
#       [ 9],
#       [10],
#       [11]])
arr.reshape(2,6)
# array([[ 0,  1,  2,  3,  4,  5],
#       [ 6,  7,  8,  9, 10, 11]])
arr.reshape(6,2)
# array([[ 0,  1],
#       [ 2,  3],
#       [ 4,  5],
#       [ 6,  7],
#       [ 8,  9],
#       [10, 11]])
arr = np.arange(20)
# array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
arr.reshape(-1,5)
# array([[ 0,  1,  2,  3,  4],
#       [ 5,  6,  7,  8,  9],
#       [10, 11, 12, 13, 14],
#       [15, 16, 17, 18, 19]])
arr.reshape(5,-1)
# array([[ 0,  1,  2,  3],
#       [ 4,  5,  6,  7],
#       [ 8,  9, 10, 11],
#       [12, 13, 14, 15],
#       [16, 17, 18, 19]])
arr.reshape(-1,10)
# array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
#       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
arr.reshape(2,-1)
# array([[0,  1],  
#        [2,  3],  
#        [4,  5],  
#        [6,  7],  
#        [8,  9],
#        [10, 11], 
#        [12, 13], 
#        [14, 15], 
#        [16, 17], 
#        [18, 19]])
arr = np.arange(20).reshape(4,5)
arr
# array([[ 0,  1,  2,  3,  4],
#       [ 5,  6,  7,  8,  9],
#       [10, 11, 12, 13, 14],
#       [15, 16, 17, 18, 19]])
arr1 = np.arange(4).reshape(-1,2)
arr1
# array([[0, 1],
#       [2, 3]])
arr = np.arange(30).reshape(3,2,5)
arr.shape
# (3, 2, 5)
x = np.arange(6).reshape(-1,3)
x
# array([[0, 1, 2],
#       [3, 4, 5]])

 

 

Python NumPy ndarray transpose()

print(arr.transpose().shape)
arr.transpose()
# (5, 4)
# array([[ 0,  5, 10, 15],
#       [ 1,  6, 11, 16],
#       [ 2,  7, 12, 17],
#       [ 3,  8, 13, 18],
#       [ 4,  9, 14, 19]])
arr1
# array([[0, 1],
#       [2, 3]])
arr1.transpose()
# array([[0, 2],
#       [1, 3]])

 

Python NumPy ndarray sort()

np.random.seed(42)
arr = np.random.randint(1,100,size=10)
print(arr)
print(-np.sort(-arr)) #부호를 이용하여 내림차순으로 정렬

# [52 93 15 72 61 21 83 87 75 75]
# [93 87 83 75 75 72 61 52 21 15]

lst = [1,32,4,1,20]
lst.sort(reverse=True)
print(lst)
# [32, 20, 4, 1, 1]

 

sort() / sorted()

  • 기존 배열 값을 변화시키는지, 요청한 배열로 리턴해 주는지,
  • 함수에 return이 있는지 없는지, 있어야 하는지 없어야 하는지 꼭 잘 알아둬야 한다.
  • 작업하고 결과값을 꼭 확인하는 습관을 들이자.
A = [5,23,2,1,5]
print(A.sort()) # None 리턴 없다
A # [1, 2, 5, 5, 23]

a1 = [5, 23, 2, 1, 5]
print(sorted(a1)) # [1, 2, 5, 5, 23]
a1 # [5, 23, 2, 1, 5]

 

 

Python NumPy ndarray T Operation

x = np.arange(6).reshape(-1,3)
x
# array([[0, 1, 2],
#       [3, 4, 5]])

x.T
# array([[0, 3],
#       [1, 4],
#       [2, 5]])

 

# 연습문제 2) 0~20까지의 숫자 배열을 만든 다음에 arr1에는 짝수, arr2는 홀수가 들어간 배열을 출력해보자.

import numpy as np

arr = np.arange(21)
arr1 = []
arr2 = []
for i in range(len(arr)):
  arr_0 = arr[i]
  if arr_0%2==0:
    arr1.append(arr_0)
  else:
    arr2.append(arr_0)

print(arr1)
print(arr2)

# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
# [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
import numpy as np

arr = np.arange(0,21)
arr1 = []
arr2 = []
for i in arr:
    if arr[i] %2==0:
        arr1.append(arr[i])
    else:
        arr2.append(arr[i])
import numpy as np
Arr = np.arange(0,21)

Arr1 = Arr[Arr%2==0]
Arr2 = Arr[Arr%2!=0]
 
print(Arr1) # [ 0  2  4  6  8 10 12 14 16 18 20]
print(Arr2) # [ 1  3  5  7  9 11 13 15 17 19]

print(Arr1[1]) # 2
print(Arr[-1]) # 20
print(Arr[:4]) # [0 1 2 3]

 

range()와 np.arange() 비교

range(start, end) 함수는 start와 end 사이의 연속적인 숫자들을 리턴하는 함수입니다. 예를 들어, range(1, 5)는 [1, 2, 3, 4](1을 포함하고 5는 포함하지 않는)의 연속적인 숫자 범위를 리턴합니다.

range로 생성한 배열 중 여러개를 동시에 변형하는 것이 안 되는 것에 비해

lst = list(range(6))
lst 
# [0, 1, 2, 3, 4, 5]
lst = list(range(6))
print(lst) # [0, 1, 2, 3, 4, 5]

lst[3]=-1
print(lst) # [0, 1, 2, -1, 4, 5]

lst[2:5] = -1 # 할당 안되죠..
print(lst) # TypeError: can only assign an iterable

넘파이에서는 아래와 같이 바뀌게 됩니다.

import numpy as np

arr1d = np.arange(8)
print(arr1d) # [0 1 2 3 4 5 6 7]

arr1d[3:6]=100 
print(arr1d) # [  0   1   2 100 100 100   6   7]

 

Python NumPy ndarray 불리안 배열

import numpy as np
arr = np.array([0,1,2,3,4])
print(arr[[True, False, True, False, True]])
# [0 2 4]

 

Python NumPy ndarray 정수 배열을 사용한 인덱싱

import numpy as np
arr2d = np.arange(20).reshape(4,5)
print(arr2d)
# [[ 0  1  2  3  4]
# [ 5  6  7  8  9]
# [10 11 12 13 14]
# [15 16 17 18 19]]

print(arr2d[[0,2]]) #0행과 2행# Multi index는 []하나 더 추가해야 함
# [[ 0  1  2  3  4]
# [10 11 12 13 14]]
print(arr2d[[0,3],[4]])
# [ 4 19]
print(arr2d[[0,1],[4,3]])
# [4 8]
print(arr2d[[0,1,2],[4,3,1]])
# [ 4  8 11]

Python NumPy ndarray 슬라이싱, 인덱싱

import numpy as np
arr2d = np.arange(20).reshape(4,-1)

print(arr2d)
# [[ 0  1  2  3  4]
# [ 5  6  7  8  9]
# [10 11 12 13 14]
# [15 16 17 18 19]]

print(arr2d[0]) 
# 첫 행
# [0 1 2 3 4]
print(arr2d[1][2]) 
# 재귀적 접근/ 1행 2열
# 7
print(arr2d[1,2]) 
# 컴마를 이용하여 쉽게 인덱싱을 할 수 있음
# 7v
print(arr2d[:3,:2]) 
# 3행까지 가져오고 2열까지 가져오세요. 
# 행과 열을 함께 접근하려면 컴마 사용함. 
# [[ 0  1]
# [ 5  6]
# [10 11]]

 

 

 

※ Recursion 재귀

컴퓨터 과학에 있어서 재귀(再歸, Recursion)는 자신을 정의할 때 자기 자신을 재참조하는 방법을 뜻하며, 이를 프로그래밍에 적용한 재귀 호출(Recursive call)의 형태로 많이 사용된다. 또 사진이나 그림 등에서 재귀의 형태를 사용하는 경우도 있다. (위키백과)

# C
 unsigned int factorial(unsigned int n)
 {
     if (n <= 1)
         return 1;
     else
         return n * factorial(n-1);
 }

# 스칼라
def factorial(n: Int): Int = if (n <= 1) 1 else n * factorial(n-1)

Recursive function 재귀함수

재귀 함수의 'recursive'는 ‘반복되는’이라는 의미를 갖고 있습니다. 프로그래밍에서 재귀 함수는 어떤 일을 하는 함수를 만들었을 때, 그 함수 안에서 자기 자신을 다시 불러서 함수가 실행되도록 만든 것입니다.

예를 들어, n까지의 합을 구하는 함수를 프로그램하기 위해 3까지의 합을 구하는 것을 생각해 봅시다. 계산식 3+2+1의 경우, 3+2까지의 합으로도 표현할 수 있습니다. 그리고 2까지의 합도 2+1까지의 합으로 표현할 수 있지요. 따라서 n까지의 합은 ‘n+n-1까지의 합‘으로 표현할 수 있습니다. n까지의 합을 구하는 위 함수를 sum(n)이라고 이름 짓는다면 sum 함수 안에서 또 sum 함수를 불러서 계산을 실행하게 되는 것이지요.

재귀 함수는 어디서든 볼 수 있습니다. 프랙털 도형이 자기 자신과 같은 모양의 작은 도형을 무한 개 그리는 모습을 재귀 함수의 예로 들 수 있지요. 피보나치 수열이나 하노이의 탑 알고리즘 또한 다음 수열이나 해법을 도출하기 위해서 앞 수열의 수를 가져다 사용하는 것을 생각해보면 재귀 함수라는 것을 잘 알 수 있습니다.

재귀 함수는 이처럼 똑같은 구조의 함수를 반복해서 사용할 필요가 있을 때 적용하는 것입니다. 프로그래밍에 재귀함수를 적용하면 연산식은 재귀함수를 이용하여 연산을 끝없이 반복하게 되지요. 만일 재귀 함수를 이용한 연산을 끝내려면 연산을 끝낼 수 있는 조건인 '탈출 조건'을 정해주어야 합니다. 만약 탈출 조건이 정해지지 않으면 프로그램이 연산을 멈추지 않는 무한 루프 상태에 빠지기 때문입니다.

(천재학습백과 초등 소프트웨어 용어사전)


Python NumPy ndarray 유니버설 함수

import numpy as np
arr = np.arange(-3, 3).reshape(3, -1)
print(arr)
# [[-3 -2]
# [-1  0]
# [ 1  2]]

print(np.exp(arr))
# [[0.04978707 0.13533528]
# [0.36787944 1.        ]
# [2.71828183 7.3890561 ]]

 

Python NumPy ndarray 소수점 버리기

import numpy as np
arr = np.arange(-3, 3).reshape(3, -1)
print(arr)
# [[-3 -2]
# [-1  0]
# [ 1  2]]

print(np.floor(arr))
# [[-3. -2.]
# [-1.  0.]
# [ 1.  2.]]

 

Python NumPy ndarray 이항 유니버설 함수

import numpy as np

arr1 = np.arange(8).reshape(2,-1)
arr2 = np.arange(-40,40,10).reshape(2,-1)
print(arr1)
print(arr2)
print("-----------------------")
print(np.maximum(arr1,arr2)) # 같은 자리 원소에서 가장 큰 값
print(np.subtract(arr1,arr2)) # 같은 자리 원소 뺄셈
print(np.multiply(arr1,arr2)) # 같은 자리 원소끼리 곱셈

# [[0 1 2 3]
# [4 5 6 7]]
# [[-40 -30 -20 -10]
# [  0  10  20  30]]
# -----------------------
# [[ 0  1  2  3]
# [ 4 10 20 30]]
# [[ 40  31  22  13]
# [  4  -5 -14 -23]]
# [[  0 -30 -40 -30]
# [  0  50 120 210]]

 

Python NumPy ndarray 통계 메서드

import numpy as np

arr = np.arange(4).reshape(2,2)
print(arr)
print("--------------")

print(arr.sum())
print(arr.sum(axis=0)) # axis=0 세로 결합 [0+2 1+3]
print(arr.sum(axis=1)) # axis=1 가로 결합 [0+1 2+3]  
print(arr.mean(axis=0)) # 평균값 # 수 위계에서 층위가 높은 실수값이 나온다. 
print(arr.mean(axis=1)) # 평균값

# [[0 1]
# [2 3]]
# --------------
# 6
# [2 4]
# [1 5]
# [1. 2.]
# [0.5 2.5]

 

Python NumPy ndarray where

  • x if 조건 else y의 벡터화 버전
  • numpy를 사용하여 배열을 빠르게 처리할 수 있으며, 다차원도 간결하게 표현이 가능
xarr = np.array([100,200,300,400])
yarr = np.array([1,2,3,4])
cond = np.array([True,False,True,False])

print(xarr)
print(yarr)
print(cond)
print("-----------------------------------------------")
result = np.where(cond,xarr,yarr)
print(result)
print(np.where(xarr>200,max(xarr),0))
result

# [100 200 300 400]
# [1 2 3 4]
# [ True False  True False]
# -----------------------------------------------
# [100   2 300   4]
# [  0   0 400 400]
# array([100,   2, 300,   4])
 
 

Python NumPy ndarray eye() 단위행렬

대각 원소 1이고, 나머지는 0인 n차 정방행렬을 말하며, numpy의 eye()함수를 사용하여서 만들 수 있음

vimport numpy as np
identity = np.eye(4)
print(identity)

identity = np.eye(2,3)
print(identity)

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

 

Python NumPy ndarray diag() 대각행렬

diagonal matrix

영상 분야 최적화 논문 보면 diagonal matrix로 연산하는 경우가 있는데,

2차원 연산을 1차원 연산으로 할 수도 있고, 반복 시 연산값 재활용으로 고속화 가능, 블럭 연산도 가능하다고 함

x = np.arange(9).reshape(3,-1)
print(x)
# [[0 1 2]
# [3 4 5]
# [6 7 8]]

print(np.diag(x)) # diagonal matrix
# [0 4 8]
 
 
 
 

Python NumPy ndarray dot()

  • 원소 간의 곱(element-wise product)
  • 벡터의 내적(행렬의 곱)
import numpy as np
a = np.arange(4).reshape(-1,2)

print(a)
# [[0 1]
# [2 3]]

print(a*a) # dot product
# [[0 1]
# [4 9]]

print(np.multiply(a,a))
# [[0 1]
# [4 9]]

print(np.dot(a,a)) # 행렬의 곱
# [[ 2  3]
# [ 6 11]]

print(a.dot(a)) # 위와 같다
# [[ 2  3]
# [ 6 11]]
 

행렬의 곱셈

‘발 없는 말이 천리 간다’는 우리나라 속담의 뜻은 ‘말이 이 사람에서 저 사람으로 전달되면서 변질되어 나중에는 전혀 엉뚱한 소문으로 퍼지게 된다’는것이다. 이 속담에서 말이란 진실이

terms.naver.com

 
 
 

Python NumPy ndarray matmul()

matrix multiplication

import numpy as np

a = np.random.randint(-3,3,10).reshape(2,5)
b = np.random.randint(0,5,15).reshape(5,3)
print(a.shape, b.shape)
# (2, 5) (5, 3)

ab = np.matmul(a,b)
print(ab.shape, '\n')
# (2, 3) 

print(ab)
# [[ -7  -4 -14]
# [  0  -3 -13]]

np.dot(a,b)
# array([[ -7,  -4, -14],
#       [  0,  -3, -13]])


time

시간값을 얻고 싶다면 time을 활용해 보자.

너무 정리를 잘 해 주신 포스팅

https://www.daleseo.com/python-time/

 

파이썬의 time 모듈로 시간 데이터 다루기

Engineering Blog by Dale Seo

www.daleseo.com

import time
python_list = [x ** 3 + 10 for x in python_list]

# 결과 : CPU times: user 328 ms, sys: 52.9 ms, total: 381 ms, 
Wall time: 382 ms
import time
numpy_arr = numpy_arr ** 3 + 10

# 결과 : CPU times: user 4.37 ms, sys: 850 ms, total: 5.22 ms, 
Wall time: 9.3 ms

 


 

 

+ Recent posts