python이 다른 언어보다 느린 이유.
- data = 이진 데이터
- dimensions : 배열 구조
- strides = 증감크기(type 크기)
- length = 시퀀스 길이
- items = 요소(주소)
NumPy 배열
- 숫자 데이터를 더 쉽고 편리하게 다룰 수 있게 도와주는 패키지
- 숫자 데이터를 효과적으로 다룰 수 있다 그래서 데이터 과학이나 분석에 많이 사용되는 패키지다.
- 다차원 배열 자료구조 클래스인 ndarray(N-dimensional Array) 클래스를 지원한다.
- 벡터와 행렬을 사용하는 선형대수 계산에 주로 사용된다.
- 배열(array)이란 순서가 있는 같은 종류(type)의 데이터가 저장되며 요소 개수가 변경 불가능한 자료형이다.
- 그래서 구조적으로 더 빠른 연산을 보여주며 메모리가 더 효율적이다.
- list는 타입이 다른 값들이 들어오기 때문에 위 사진처럼 연속적인 저장이 불가능하다.(타입별 크기가 다르기 때문)
- 그래서 list는 중간에 끼워 넣고 길이 설정이 필요 없는 유연성이 있지만 느리다.
넘파이 배열
- 넘파이 배열 연산은 C로 구현된 내부 반복문을 사용하기 때문에 파이썬 반복문에 비해 속도가 빠르다.
- 모든 차원벡터화 연산 을 이용하여 간단한 코드로도 복잡한 선형대수 연산을 수행할 수 있다.
import numpy as np # np라는 이름으로 import하는 것이 관례라고 한다.
- numpy의 array 메서드 인수로 시퀀스 자료형을 넣으면(주로 list) ndarray클래스 객체(넘파이 배열)로 변환해 준다
- 만들어진 ndarray 객체의 표현식을 보면 바깥쪽에 array()란 것이 붙어 있을 뿐 리스트와 동일한 구조처럼 보인다
- 하지만 많은 차이점이 존재한다.
- shape를 통해 배열의 모양을 알 수 있다.
ar = np.array([range(1,11) for i in range(6)])
print(ar.shape) # (1,10) = 1 X 10 1차원 배열을 뜻한다.
# (6,10) = 6 X 10 2차원 배열을 뜻한다.
print(type(ar)) # ndarray클래스의 instance임을 볼 수 있다.
ar+ar
- 선언 시에 정수 실수가 혼합된 리스트를 사용하는 경우 표현 범위가 더 큰 자료형(실수)으로 변환된다
- 실수, 정수, 문자열은 문자열이 가장 큰 자료형이므로 문자열로 변환된다.
- numpy속성 중. dtype으로 넘파이 배열의 자료형을 확인할 수 있다.
ar2 = np.array([0.1,'123',123])
print(ar2)
print(ar2.dtype) # U32 = unicode string 32(최대 32글자씩) 타입을 뜻함.
ar3 = np.array([ i for i in range(3,10,3)],'i8') #'i8'처럼 타입 명시가 가능함.
print(ar3,ar3.dtype)
ar4 = np.array([_ for _ in range(2,10,2)],'f8') # 숫자 지정은 자동으로 byte단위로 카운팅함
print(ar4,ar4.dtype)
ar5 = np.array(['가나다라마' for i in range(4)],'U')# 숫자안쓰면 기본값으로 dynamic typing 된다.
print(ar5, ar5.dtype)
- 무한대는 inf(infinity)로 표기하고
- 정의할 수 없는 숫자(0/0)는 nan(not a number)로 표기한다.
- 넘파이 배열 객체는 배열의 각요소에 대한 반복 연산을 하나의 명령어로 처리하는 벡터화 연산을 지원한다
- 이 방식은 리스트의 for 반복문 없이 간단하게 표현 가능하며 훨씬 빠르다.
- 벡터화 연산은 비교 연산과 논리 연산을 포함한 모든 종류의 수학 연산에 대해 적용된다.
# ex)모든 요소 데이터를 모두 2배 해야하는 경우
#리스트
data = [1,2,3]
answer = [2*d for d in data]
print(answer)
#넘파이
x = np.array(data)
print(2*x)
# array는 논리연산도 가능하다.
x = np.array([1,2,3])
y = np.array([10,20,30])
print(2*x+10)
print(x == 3)
print(y>10)
print((x == 3) & (y>10))
2차원 배열 만들기
- 수학에서 행렬(matrix) 가로줄 = 행(row) 세로줄 = 열(column)
- shape(2,3) = 2행 3열
c = np.array([[0,1,2],[3,4,5]])
print(c, c.shape)
print(len(c),len(c[0]))
ar_1 = np.array([[10,20,30,40],[50,60,70,80]])
print(ar_1)
3차원 배열 만들기
- 깊이 X 행 X 열 모양을 갖는다.
- shpae(4,3,2) = 높이 4 행 3 열 2
#ndim 속성과 shape 속성을 이용해 배열의 크기를 구할 수 있다.
ar_2 = np.array([ar_1],[[10,20],[]])
print(ar_2.ndim,ar_2.shape)
print(ar_2)
배열은 인덱싱과 슬라이싱 모두 가능하다.
ar_1 = np.array([[10,20,30,40],[50,60,70,80]])
print(ar_1[0,:],end ="\\n\\n") # 첫번째 행 전부 출력
print(ar_1[:,1],end = "\\n\\n") #1번째 열 다 출력
print(ar_1[:2,:2],end="\\n\\n")
#reshape 함수
ar_3 = np.array([_ for _ in range(8)]).reshape(4,2) # reshape = 숫자개수만 맞는다면 이 모양으로 만들어라 라는 명령어
print(ar_3)
print(ar_1.reshape(1,8)) # 존재하는 배열도 변경 가능.
m = np.array([_ for _ in range(15)]).reshape(3,5)
print(m[1,2])
print(m[-1,-1])
print(m[1,1:3])
print(m[1:,2])
print(m[0:2,3:])
NumPy의 배열을 생성하는 Method
- zeros, ones
- zeros_like, ones_like
- empty
- arrange
- linspace, logspace
- zeros
a = np.zeros(5) ;print(a) # 0 5개만들어라
d = np.zeros(5,dtype = "U4")
print(d)
d[0] = "abcde" # U4라서 5번쨰 자리는 잘리는것을 볼 수 있다.
print(d,end ="\\n\\n")
e = np.ones((2,3,4),dtype = "i8")
print(e,end="\\n\\n")
f = np.ones_like(d,dtype = "f") #like가 붙으면 d랑 같은 shape로 만들고, 다 1로 채워라 라는 소리임.
print(f)
g = np.empty((4,3)) # empty는 빠르게 만들김나 하고 초기화 X이다.(쓰레기 값 저장되어 있음.)
print(g)
print(np.arange(1,10,2)) # range함수와 같은역할을 하는 arange(시작,끝,증감) 함수
print(np.linspace(0,100,5)) #동일한 간격으로 지정한 구간의 수만큼 분할
print(np.logspace(0,100,5)) #로그 간격으로 지정한 구간의 수만큼 분할
H = np.zeros((4,3))
print(H) #4 X3 행열
print(H.T) #3 X 4 행열로 변경
print(H.reshape(2,6)) # 2 X 6 행열로 reshape
print(H.reshape(2,2,-1)) # (2X2)으로 나누어 떨어질 때 열은 알아서 맞춰줘 가능.
print(H.flatten()) #다차원 배열을 1차원으로 만드는 함수
배열 연결
- hstack = 행의 수가 같은 두 개 이상의 배열을 옆으로 연결
- vstack = 열의 수가 같은 두 개 이상의 배열을 위로 연결
- dstack = 행 X 열의 수가 같은 두 개 이상의 배열을 깊이 방향으로 배열을 함침
- stack = 사용자가 지정한 차원(축)을 기준으로 배열을 연결한다 , 연결하고자 하는 배열들의 크기가 모두 같아야 한다.
- axis = 0(깊이방향)이 default 값이고 axit값에 따라 어느 방향으로 값을 추가할지 결정한다.
특수 메서드 indexer(메서드이지만 ()를 사용하지 않고 인덱싱과 같이 []를 사용하여 사용한다.)
- r_ = hstack과 동일한 역할을 한다. (row)
- c_ = vstack과 동일한 역할을 한다 (column)
- tile = 동일한 배열을 반복하여 연결한다.
a1 = np.ones((2,2))
a2 = np.zeros((2,2))
print(np.hstack([a1,a2]),end="\\n\\n") #행의 수가 같은 두 개 이상의 배열을 옆으로 연결
print(np.vstack([a1,a2]),end="\\n\\n") #열의 수가 같은 두 개 이상의 배열을 위로 연결
print(np.dstack([a1,a2]),end="\\n\\n")
print(np.stack([a1,a2]),end="\\n\\n")
print(np.stack([a1,a2],axis=1),end="\\n\\n")
print(np.r_[a1,a2],end="\\n\\n")
print(np.c_[a1,a2],end="\\n\\n")
print(np.tile(a1,(3,2)),end="\\n\\n") # 행방향 3번 반복하고, 열방향 2번 반복
zer = np.zeros((3,3))
one = np.ones((3,2))
rang = np.arange(10,151,10).reshape(-1,5)
result = np.hstack([zer,one])
result = np.vstack([result,rang])
result = np.tile(result,(2,1))
result