// 실습 코드
import math
math.factorial(4) # 24
from math import factorial을 이용한 팩토리얼 계산
// 실습 코드
from math import factorial
factorial(4) # 24
// 실습 코드
for _ in ['11', 'number']:
try:
int(_)
except ValueError as m:
print(m)
else:
print("No Error!")
finally:
print('Finally Code')
print('\n') # \n: enter key
// 실습 코드
school = {'1반':[150, 156, 179, 191, 199], '2반':[150, 195, 179, 191, 199]}
try:
for class_number, students in school.items():
for student in students:
if student > 190:
print(class_number, '190을 넘는 학생이 있습니다.')
# break 바로 상위 for문은 종료되지만 최고 상위 for문은 종료되지 않는다.
raise StopIteration
except StopIteration:
print('정상 종료')
// 실습 코드
a = 10
# True인 경우
print("1. assert True인 경우")
assert a == 10, "a is not 10"
print("끝1")
# False인 경우
print("2. assert False인 경우")
assert a == 999, "a is not 999"
print("끝2")
# 1. assert True인 경우
# 끝1
# 2. assert False인 경우
# ---------------------------------------------------------------------------
# AssertionError Traceback (most recent call last)
# <ipython-input-4-e24b2003f266> in <cell line: 11>()
# 9 # False인 경우
# 10 print("2. assert False인 경우")
# ---> 11 assert a == 999, "a is not 999"
# 12
# 13 print("끝2")
# AssertionError: a is not 999
// 실습 코드
# 사용자로부터 숫자를 계속 입력받다가 s or S를 입력하면 합계가 출력되는 코드에서
# 다른 문자를 입력했을 때, 예외처리를 해보세요.
c = 0
d = 1
while (d == 1):
a = input('값을 입력해주세요.')
try:
if(a == 's' or a == 'S'):
d = 0 # break
else:
a = int(a)
c += a
except:
continue
print('합계는', c)
// 실습 코드
import numpy as np
n = 10000000
numpy_arr = np.arange(n)
python_list = list(range(n))
// 실습 코드
%%time
python_list = [x**3 + 10 for x in python_list]
# CPU times: user 3.68 s, sys: 297 ms, total: 3.98 s
# Wall time: 4.03 s
Numpy 배열 연산 시간
// 실습 코드
%%time
numpy_arr = numpy_arr*3+10
# CPU times: user 121 ms, sys: 64.8 ms, total: 185 ms
# Wall time: 162 ms
// 실습 코드
import numpy as np
A = [1, 2, 3, 4]
a = np.array(A)
print(type(a))
print(a)
# list와 array의 차이
// 실습 코드
lis = [1, 2, 3]
lis + 3 # 자료형이 달라서 연산이 안됨
# TypeError Traceback (most recent call last)
# <ipython-input-8-fd62dc38414a> in <cell line: 2>()
# 1 lis = [1, 2, 3]
# ----> 2 lis + 3 # 자료형이 달라서 연산이 안됨
# TypeError: can only concatenate list (not "int") to list
// 실습 코드
import numpy as np
A = np.array([1, 2, 3])
print(A + 3) # 연산 가능(=> 브로드캐스팅)
print(A / 3)
# [4 5 6]
# [0.33333333 0.66666667 1. ]
// 실습 코드
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
arr
# array([[1, 2, 3],
# [4, 5, 6]])
// 실습 코드
# 같은 크기의 배열 간의 산술 연산은 배열의 각 원소 단위로 적용됨
arr + arr # 벡터화가 가능하다. element-wise
# array([[ 2, 4, 6],
# [ 8, 10, 12]])
// 실습 코드
lit= [[1,2, 3], [4, 5, 6]]
lit + lit
# [[1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6]]
// 실습 코드
lit= [[1,2, 3], [4, 5, 6]]
lit2 = lit
result = []
for i in range(len(lit)):
temp = []
for j in range(len(lit[i])):
temp.append(lit[i][j] + lit2[i][j])
result.append(temp)
print(result)
# [[2, 4, 6], [8, 10, 12]]
// 실습 코드
arr / arr # float 형태로 나옴
# array([[1., 1., 1.],
# [1., 1., 1.]])
다른 모양의 배열 간의 산술 연산을 수행하는 기능
// 실습 코드
arr
# array([[1, 2, 3],
# [4, 5, 6]])
arr2 = np.array([100, 200, 300])
arr + arr2
# array([[101, 202, 303],
# [104, 205, 306]])
arr3 = np.array([[100], [200]])
arr + arr3
# array([[101, 102, 103],
# [204, 205, 206]])
arr4 = np.array([100, 200, 300, 400])
arr + arr4 # 행이나 열이 맞아야 실행됨
# ValueError Traceback (most recent call last)
# <ipython-input-19-5c75a12d5480> in <cell line: 2>()
# 1 arr4 = np.array([100, 200, 300, 400])
# ----> 2 arr + arr4 # 행이나 열이 맞아야 실행됨
# ValueError: operands could not be broadcast together with shapes (2,3) (4,)
// 실습 코드
my_list = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9]]])
print(my_list) # 3차원
print('차원 : ', my_list.ndim)
print('모양 : ', my_list.shape)
print('크기 : ', my_list.size)
print('데이터 타입 : ', my_list.dtype)
print('각 원소의 크기 : ', my_list.itemsize) # 배열의 각 요소의 크기를 바이트 단위로 변환
# int64는 8바이트 정수
# [[[1 2 3]
# [4 5 6]
# [7 8 9]]]
# 차원 : 3
# 모양 : (1, 3, 3)
# 크기 : 9
# 데이터 타입 : int64
# 각 원소의 크기 : 8
// 실습 코드
np.array(range(20))
np.zeros(5) # 모델 초기화나 임시 데이터 생성 등에 유용하게 쓰임
np.ones((3,3))
# array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
# array([0., 0., 0., 0., 0.])
# array([[1., 1., 1.],
# [1., 1., 1.],
# [1., 1., 1.]])
np.zeros_like()와 np.ones_like()를 사용하여 특정 배열과 동일한 크기의 배열 생성
// 실습 코드
arr1 = np.array([[1, 2, 3, 1], [2, 4, 5, 6]])
arr1
# array([[1, 2, 3, 1],
# [2, 4, 5, 6]])
arr2 = np.ones_like(arr1)
arr2
# array([[1, 1, 1, 1],
# [1, 1, 1, 1]])
arr3 = np.zeros_like(arr1)
arr3
# array([[0, 0, 0, 0],
# [0, 0, 0, 0]])
// 실습 코드
arr4 = np.arange(5)
np.arange(-3, 3)
np.arange(3, 50, 5) # 시작, 끝, 간격
# array([ 3, 8, 13, 18, 23, 28, 33, 38, 43, 48])
np.linspace()로 균등 분할 배열 생성
// 실습 코드
np.linspace(0, 1, 6) # (start, stop, num, endpoint, restep) 범위 내에서 주어진 sample 갯수만큼 생성
# 0에서 1사이에서 6개 생성(주로 그림 그릴 때 사용함)
# array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])
// 실습 코드
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.hstack([a, b]))
print(np.concatenate((a, b), axis=0))
# [1 2 3 4 5 6]
# [1 2 3 4 5 6]
// 실습 코드
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 두 배열을 왼쪽에서 오른쪽으로 붙이기
print(np.hstack([a, b]))
print(np.concatenate((a, b), axis=0))
# [[1 2 5 6]
# [3 4 7 8]]
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
수직 결합: np.vstack()를 사용한 열 기준 결합
// 실습 코드
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 두 배열을 위에서 아래로 붙이기
print(np.vstack([a, b]))
# [[1 2 3]
# [4 5 6]]
// 실습 코드
np.concatenate((a, b), axis=1) # concatenate는 2D에서 문제가 없음.(1차원은 불가능)
# AxisError Traceback (most recent call last)
# <ipython-input-58-9b5fa525581a> in <cell line: 1>()
# ----> 1 np.concatenate((a, b), axis=1) # concatenate는 2D에서는 문제가 없음.
# AxisError: axis 1 is out of bounds for array of dimension 1
// 실습 코드
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
np.concatenate((a, b), axis=1)
# array([[1, 2, 5, 6],
# [3, 4, 7, 8]])
// 실습 코드
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
np.column_stack([a, b])
# array([[1, 4],
# [2, 5],
# [3, 6]])
// 실습 코드
import random # 난수를 발생시키는 모듈
random.random() # 리턴값 0 <= 리턴값 <= 1
from random import random
random() # random을 두 번 안써도 됨
// 실습 코드
random.uniform(100, 200) # a <= 실수 <= b 사이의 실수를 리턴
random.choice()로 랜덤 요소 선택
// 실습 코드
data = [1, 2, 3, 4, 5, 6]
random.choice(data)
random.seed()로 난수 생성기 시드 고정
// 실습 코드
import random
random.seed(42) # 난수 생성기의 시드를 지정
// 실습 코드
import numpy as np
# rand : 0과 1사이의 균일 분포에서 난수 생성
print("Random number between 0 and 1 : ", np.random.rand())
# randn : 표준 정규 분포(중심이 0, 표준편차 1)에서 난수 생성
print("Random number from standard nomal distribution : ", np.random.randn())
# randint : 주어진 범위에서 임의의 정수 생성
print("Random number between 1 and 10 : ", np.random.randint(1, 10))
# random : 0과 1사이의 군일 분포에서 난수 생성(rand와 비슷하지만 다른 형태의 인자를 받음)
print("Random number between 0 and 1 : ", np.random.random())
# 랜덤 샘플링 : 주어진 집합에서 임의의 요소로 선택하는 과정
# choice : 주어진 배열에서 임의의 요소 선택
arr = np.array([1, 2, 3, 4, 5])
print("Random choice from array : ", np.random.choice(arr))
# shuffle : 배열을 무작위로 섞음(원래 배열을 바꿈)
np.random.shuffle(arr)
print("Array after shuffle : ", arr)
# permutation : 배열의 무작위 순열을 반환(원래 배열을 바꾸지 않음)
print("Random permutation of array : ", np.random.permutation(arr))
# Random number between 0 and 1 : 0.6801893964823851
# Random number from standard nomal distribution : 0.6092488451859588
# Random number between 1 and 10 : 6
# Random number between 0 and 1 : 0.9108681131123196
# Random choice from array : 2
# Array after shuffle : [5 4 3 1 2]
# Random permutation of array : [1 5 4 2 3]
// 실습 코드
# 로또 번호 생성기를 만들어 보세요
import numpy as np
import random
num = int(input("로또 번호를 몇개 생성할까요 ? >"))
arr = []
for i in range(num):
for j in range(6):
arr.append(np.random.randint(1, 45))
print("%d.로또번호: %s" %(i+1, arr))
arr = []
# 답안 1
import random
def make_lotto(count):
for i in range(count):
numbers = list(range(1, 46))
random.shuffle(numbers)
lotto_num = numbers[:6]
lotto_num.sort()
print(f'{i+1}.로또번호 : {lotto_num}')
count = int(input('로또 번호를 몇 개 생성할까요 ? >'))
make_lotto(count)
# 답안 2
import numpy as np
def make_lotto(count):
for i in range(count):
lotto_num = []
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)
// 실습 코드
arr = np.zeros((3, 2))
arr.flatten()
# array([0., 0., 0., 0., 0., 0.])
np.reshape()로 배열 모양 변경, -1을 활용한 자동 계산
// 실습 코드
arr = np.arange(20)
print(arr.reshape(5, 4))
print(arr.reshape(4, 5))
print(arr.reshape(-1, 10)) # -1을 사용하면 shape을 명시하지 않아도 자동으로 채워줌. -1: 약수로 들어감.
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]
# [12 13 14 15]
# [16 17 18 19]]
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
# [[ 0 1 2 3 4 5 6 7 8 9]
# [10 11 12 13 14 15 16 17 18 19]]
// 실습 코드
arr = np.arange(784)
arr.reshape(8, -1).shape
# (8, 98)
// 실습 코드
arr = np.arange(20).reshape(4, 5)
print(arr)
print(arr.transpose().shape)
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
# (5, 4)
// 실습 코드
arr2 = np.arange(30).reshape(3, 2, 5)
print(arr2)
print(arr2.transpose().shape) # 축이 변해버려서 3차원부터는 사용하지 않음
# [[[ 0 1 2 3 4]
# [ 5 6 7 8 9]]
# [[10 11 12 13 14]
# [15 16 17 18 19]]
# [[20 21 22 23 24]
# [25 26 27 28 29]]]
# (5, 2, 3)
np.swapaxes()로 축 교환
// 실습 코드
a = np.arange(3).reshape(1, 3)
y = np.swapaxes(a, 0, 1) # 0은 가장 높은 차수의 축, 2차원 / 1은 그 다음 높은 차수의 축, 1차원 즉. 원소의 행과 열을 바꾸라는 것
print(y)
print(y.shape)
# [[0]
# [1]
# [2]]
# (3, 1)
// 실습 코드
# 0 ~ 20까지의 숫자를 배열을 만든 다음에 arr1에는 짝수, arr2는 홀수가 들어간 배열을 출력해보자.
import numpy as np
arr = np.arange(21)
arr1 = []
arr2 = []
for i in arr:
if arr[i] % 2 == 0:
arr1.append(arr[i])
else:
arr2.append(arr[i])
print(arr1)
print(arr2)
# numpy 사용
import numpy as np
arr = np.arange(21)
arr1 = arr[arr % 2 == 0]
arr2 = arr[arr % 2 != 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]
# [ 0 2 4 6 8 10 12 14 16 18 20]
# [ 1 3 5 7 9 11 13 15 17 19]
// 실습 코드
arr1d = np.arange(8)
print(arr1d[1]) # 슬라이싱도 가능
print(arr1d[-1])
print(arr1d[:4])
# 1
# 7
# [0 1 2 3]
다차원 배열의 인덱싱
재귀적 접근과 콤마(,) 기반 접근 비교
// 실습 코드
arr2d = np.arange(20).reshape(4, -1)
print(arr2d)
print(arr2d[0])
print(arr2d[1][2]) # 재귀적 접근
print(arr2d[1, 2]) # 콤마(,)를 이용하여 쉽게 인덱싱을 할 수 있음.
print(arr2d[:3][:2]) # 재귀적 접근
print(arr2d[:3, :2]) # 다름 !!
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
# [0 1 2 3 4]
# 7
# 7
# [[0 1 2 3 4]
# [5 6 7 8 9]]
# [[ 0 1]
# [ 5 6]
# [10 11]]
// 실습 코드
arr2d = np.arange(20).reshape(4, 5)
print(arr2d)
# array([4, 9])
print(arr2d[[0, 1], [4]])
print(arr2d[[0, 1], [4, 3]])
print(arr2d[[0, 1, 2], [4, 3, 1]])
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
# [4 9]
# [4 8]
# [ 4 8 11]
멀티 인덱스 사용법
// 실습 코드
arr = np.arange(10)
print(arr[[0, 2, 4, 6]]) # arr[0, 2, 4, 6]이 아닌, multi index로 접근을 해야함
print(arr[[3, 0, 1]])
# [0 2 4 6]
# [3 0 1]
// 실습 코드
# 브로드캐스팅 지원(중요!!!!!!!!!!!!!!!!)
lst = list(range(6))
print(lst)
lst[2:5] = -1 # list는 브로드캐스팅을 지원하지 않는다.
# TypeError Traceback (most recent call last)
# <ipython-input-136-3a4aff75913c> in <cell line: 4>()
# 2 lst = list(range(6))
# 3 print(lst)
# ----> 4 lst[2:5] = -1 # list는 브로드캐스팅을 지원하지 않는다.
# TypeError: can only assign an iterable
// 실습 코드
lst[3] =- 1
print(lst[3])
// 실습 코드
arr1d = np.arange(6)
print(arr1d)
arr1d[3:5] = -1 # array는 브로드캐스팅을 지원한다 !!
print(arr1d)
# [0 1 2 3 4 5]
# [ 0 1 2 -1 -1 5]
// 실습 코드
arr1 = np.arange(8).reshape(2, -1)
arr2 = np.arange(-40, 40, 10).reshape(2, -1)
print(arr1)
print(arr2)
print(np.maximum(arr1, arr2))
print(np.subtract(arr1, arr2))
print(np.multiply(arr1, arr2))
print(arr1.sum()) # 모든 원소 sum
print(np.sum(arr1, axis=0)) # 열끼리 sum
print(np.sum(arr1, axis=1)) # 행끼리 sum
# [[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]]
# 28
# [ 4 6 8 10]
# [ 6 22]
축(axis) 기반 연산(전체 합, 행 합, 열 합)
import time => 축(axis)에 따른 연산 시간 비교
// 실습 코드
# numpy에서의 메모리 접근 패턴과 캐시 최적화
import time
# 2차원 배열 생성
arr = np.random.rand(10000, 10000)
# 열의 합을 계산
start = time.time()
column_sum = np.sum(arr, axis=0)
print("Time for column sum : ", time.time() - start)
# 행의 합을 계산
start = time.time()
row_sum = np.sum(arr, axis=1)
print("Time for row sum : ", time.time() - start)
# Time for column sum : 0.13185954093933105
# Time for row sum : 0.10791897773742676
// 실습 코드
xarr = np.array([100, 200, 300, 400])
yarr = np.array([1, 2, 3, 4])
cond = np.array([True, False, True, False])
# where(조건, x, y): True일때는 xarr에 있는 값, False일때는 yarr에 있는 값을 대입하여 반환
result = np.where(cond, xarr, yarr)
print(result)
result = np.where(xarr > 200, max(xarr), 0)
print(result)
result = np.where(xarr % 3 == 0, 1, 0)
print(result)
# [100 2 300 4]
# [ 0 0 400 400]
# [0 0 1 0]
// 실습 코드
np.random.seed(10)
arr = np.random.randint(1, 100, size=10)
print(arr)
print(arr.sort()) # 원본을 직접 변경하지 않고 복사본의 정렬 상태를 반환함
print(-np.sort(-arr)) # 부호를 이용하여 내림차순으로 정렬
# [10 16 65 29 90 94 30 9 74 1]
# None
# [94 90 74 65 30 29 16 10 9 1]
공통점: 다차원 배열을 1차원 배열로 변환
// 실습 코드
# 복사본을 리턴하는 flatten()
import numpy as np
array2 = np.array([[1, 2], [3, 4]])
array3 = array2.flatten()
array3[0] = 1000
print(array2)
print(array3)
# [[1 2]
# [3 4]]
# [1000 2 3 4]
// 실습 코드
# 뷰를 리턴하는 ravel()
import numpy as np
array2 = np.array([[1, 2], [3, 4]])
array3 = array2.ravel()
array3[0] = 1000
print(array2)
print(array3)
# [[1000 2]
# [ 3 4]]
# [1000 2 3 4]
=> 복사본이 필요한 경우 flatten()
=> 원본을 유지하며 작업하려면 ravel()