import numpy as np
import timeit
'''
< 내적연산 >
-배열 간의 곱셈에서는 요소별 연산과 벡터의 내적(dot product) 연산 가능
벡터의 내적 : 두 배열 간의 곱셈
두 개의 행렬에서 첫 번째 행렬의 열 크기와 두 번째 행렬의 행 크기가 동일해야 함
m x n 행렬과 n x l 행렬 , 벡터의 내적 연산하면 m x l 생성
실습
'''
# 2행 5열
x_1 = np.arange(1,11).reshape(2,5)
#2행 3열로 출력 되어야 한다.
x_2 = np.arange(1,16).reshape(5,3)
print('x_1',x_1, end='\n\n')
print('x_2',x_2, end='\n\n')
#2행 3열로 출력
print('x_1.dot(x_2)',x_1.dot(x_2),end='\n\n')
'''
[출력]
1 * 1 + 2 * 4 + 3 * 7 + 4 * 10 + 5 * 13 이런식 으로 계속
x_1
[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
x_2
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]
[13 14 15]]
x_1.dot(x_2)
[[135 150 165]
[310 350 390]]
---------------------------------------------------------------------------
< 브로드 캐스팅 연산 > 배열과 스칼라값 사칙연산
-하나의 행렬과 스칼라 값들 간의 연산이나 행렬과 벡터 간의 연산
--방송국의 전파가 퍼지듯 뒤에 있는 스칼라값이 모든요소에 퍼지듯 연산
실습
'''
#3행 3열
x = np.arange(1,10).reshape(3,3)
print('x',x)
print('x+10',x+10)
print('x-2', x-2)
print('X*10',x*10)
print('x/3',x/3)
'''
출력:
x [[1 2 3]
[4 5 6]
[7 8 9]]
<모든열에 + 10>
x+10 [[11 12 13]
[14 15 16]
[17 18 19]]
<모든열에 -2 >
x-2 [[-1 0 1]
[ 2 3 4]
[ 5 6 7]]
<모든열 * 10>
X*10 [[10 20 30]
[40 50 60]
[70 80 90]]
<모든열 /3>
x/3 [[0.33333333 0.66666667 1. ]
[1.33333333 1.66666667 2. ]
[2.33333333 2.66666667 3. ]]
'''
'''
실습
'''
x = np.arange(1,13).reshape(4,3)
print('x',x)
v = np.arange(10,40,10)
print('v',v)
print('x+v',x+v)
'''
< 넘파이의 성능 >
-넘파이의 텐서 연산의 장점
C와 유사한 형태로 메모리를 관리하면서 C와 같은 연산 속도로 계산할 수 있다.
-메모리 구조상 요소들이 붙어있기 때문
-파이썬의 가장 큰 특징인 동적 타이핑을 포기했지만, C로 구현되어 있어 배열 연산에 있어 매우 큰 성능적 우위 확보
-대용량 배열 연산에서 넘파이가 사실상 표준으로 사용됨
연결 연산 처럼 여러 배열을 붙이는 연산에서는 일반적인 리스트에 비해 느림
-필요할 때마다 메모리 탐색 과정으로 새로운 공간을 잡아야 하기 때문
'''
def sclar_vector_product(scalar, vector):
# start = timeit.default_timer()
result = []
for value in vector:
result.append(scalar * value)
# end = timeit.default_timer()
# print("함수 수행시간: %f 초" % (end - start))
return result
iternation_max = 1000000
vector = list(range(iternation_max))
scalar = 2
# end = timeit.default_timer()
#for 문을 이용한 성능
#print('for문,',timeit.timeit(lambda : sclar_vector_product(scalar,vector)))
'''주피터에서 활용 '''
# #리스트 컴프리헨션 이용
# print('list컴프리헨션:',[scalar * value for value in range(iternation_max)])
#넘파이를 이용한 성능
#timeit.timeit(lambda : np.arange(iternation_max) * scalar)
'''
< 비교 연산 >
연산결과는 항상 불리언을 가진 배열로 추출
[브로드 캐스팅 비교연산]
-하나의 스칼라값과 벡터간의 비교연산은 벡터내 전체요소에 적용
'''
x = np.array([4,3,2,6,8,5])
print(x > 3)
'''
<요소별 비교 연산>
-두개의 배열 간 배열의 구조(shape)가 동일한 경우
-같은 위치에 있는 요소들끼리 비교연산
-[1>2,3>1,0>7]과 같이 연산이 실시된 후 이를 반환
실습
'''
x = np.array([1,3,0])
y = np.array([2,1,7])
print('x>y',x>y)
'''
<비교 연산 함수 >
[1]all과 any
-all함수 : 배열 내부의 모든 값이 참일때는 True , 하나라도 참이 아닐 경우에는 False를 반환
--and 조건을 전체 요소에 적용
-any 함수: 배열 내부의 값중 하나라도 참일때는 True, 모두 거짓일 경우 False를 반환
--or 조건을 전체 요소에 적용
'''
x = np.array([4,6,7,3,2])
print('x>3',x>3) # [ True True True False False]
print('x>3.all',all(x>3)) # False
print('x>3.any',any(x>3)) # True
print('x<10.any',any(x<10)) #True
print('x<10.all',all(x<10)) #True
print('x>10.any',any(x>10)) #False
'''
< 인덱스 반환 함수 >
where 함수 : 배열이 불린형으로 이루어졌을 때 참인 값들의 인덱스를 반환
[실습]
'''
x = np.array([4,6,7,3,2])
print('x>5', x>5)
print('np.where(x>5)', np.where(x>5))
print('np.where(x>5, 10,20)', np.where(x>5,10,20))
'''출력:
x>5 : [False True True False False]
np.where(x>5) : (array([1, 2], dtype=int64),)
np.where(x>5,10,20) : [20 10 10 20 20]
'''
'''
< 정렬된 값의 인덱스를 반환해주는 함수 >
argsort : 배열 내 값들을 작은 순서대로 인덱스를 반환
argmax : 배열 내 값들 중 가장 큰 값의 인덱스를 반환
argmin : 배열 내 값들 중 가장 작은값의 인덱스를 반환
'''
print('np.argsort(x)',np.argsort(x)) # [4 3 0 1 2]
print('np.argmax(x)',np.argmax(x)) # 2
print('np.argmin(x)',np.argmin(x)) # 4
'''
Boolean 인덱스
불린 인덱스 : 배열에 있는 값들을 반환할 특정 조건을 불린형의 배열에 넣어서 추출
-인덱스에 들어가는 배열은 불린형이어야함
-불린형 배열과 추출 대상이 되는 배열의 구조가 같아야함
'''
print('BOOLEAN타입 ', x>3) # [ True True True False False]
cond = x > 3
#x의 cond 설정
print('x[cond]',x[cond]) # [4 6 7]
print('x.shape:',x.shape) # (5,)
print('cond.shape',cond.shape) # (5,)
'''
-------------------------------------------------------------
<팬시 인덱스>
팬시 인덱스 : 정수형 배열의 값을 사용하여 해당 정수의 인덱스에 위치한 값을 반환
-인덱스 항목에 넣을 배열은 정수로만 구성되어야 함
-정수값의 범위는 대상이 되는 배열이 가지는 인덱스의 범위 내 대상이 되는 배열과 인덱스 배열의 구조(shape)가 같을 필요는 없음
'''
x = np.array([4,6,7,3,2])
cond = np.array([1,2,0,2,2,2,],int)
print('x[cond]',x[cond])
# x배열의 인덱스 위치를 가져온다. cond 1 = 6 , 2 = 7 이런식
print('x.take(cond)',x.take(cond)) # [6 7 4 7 7 7]
x= np.array([[1,4],[9,16]],int) # 2행 2열
a = np.array([0,1,1,1,0,0],int)
print('x[a]',x[a]) #행이 출력된다. a =0 ,1행 a = 1 는 2행
b = np.array([0,0,0,1,1,1],int)
print('x[b]',x[b]) # 행이 출력된다 b= 0 1행 b =1 2행
print('x[a,b]',x[a,b]) # [ 1 9 9 16 4 4] (0,0 = 1행 1열 , 1,0 = 2행 1열, 1,1은 2행 2열 이런식으로 반환 )