728x90
Numpy 다차원 배열 변수의 Assignment, Shallow copy, Deep copy
Assignment
import numpy as np
x = np.arange(5)
y = x
print(id(x), id(y))
# 같은 값 출력 - 같은 객체 참조. 같은 원소에 binding 되어있음.
print("x=", x) # [0 1 2 3 4]
print("y=", y) # [0 1 2 3 4]
x[3] = 10
print("x=", x) # [0 1 2 10 4]
print("y=", y) # [0 1 2 10 4]
Numpy 다차원 배열 변수의 view는 shallow copy
x = np.arange(5)
print("x=", x) # [0 1 2 3 4]
y = x[1:4] # index slicing
print("y=", y) # [1 2 3]
print(id(x), id(y)) # 주소 다름: 별개의 객체
y[1] = 10
print("x=", x) # [0 1 10 3 4]
print("y=", y) # [1 10 3]
x[3] = 20
print("x=", x) # [0 1 10 20 4]
print("y=", y) # [1 10 20]
# 주소 다른데, 분명 다른 객첸데,
# list slicing으로 만든 y는 x원소 그대로 갖다쓰기 때문
# == view, shallow copy of numpy
xx = x.view() # shallow copy 생성 method
print(x)
print(xx)
# same
print(id(x), id(xx)) # 주소 다름. 별도의 객체지만
# index slicing이랑 비슷한 개념
x[3] = 30
print("x = ", x) # [0 1 10 30 4]
print("xx = ", xx) # [0 1 10 30 4]
# 별도의 객체인데도 원소 하나 바꾸면 둘다 바뀜.
- list method의 indexing = ?
- list method의 copy = shallow copy
- ndarray method의 view = shallow copy
- ndarray method의 copy = deep copy
a = np.arange(24).reshape(2, 3, 4)
b = a[:,:,::2]
# axis 0방향으로 모든 원소, 1방향으로 모든 원소 갖지만
# axis 2방향으로는 step 2씩 증가하는 ndarray 객체
print(b.shape) # (2, 3, 2): axis 2방향이 반으로 줄었기 때문
b[0, 2, 0] = 88
b # 8 > 88 변경됨
a # 여기있는 8도 88로 변경됨
a[1, 2, 2] = 220
a # 220
b # 220
Numpy 다차원 배열 변수의 Deep copy: ndarray.copy
x = np.arange(4)
# y, z 모두 x를 deep copy
y = np.copy(x)
z = x.copy()
print("x=", x) # [0 1 2 3]
print("y=", y) # [0 1 2 3]
print("z=", z) # [0 1 2 3]
# 세 변수 주소 다 다름
# 두 객체 내용 변하지 않음. 세 객체 모두 다 다른 객체
x[1] = 10
print("x=", x) # [0 10 2 3]
print("y=", y) # [0 1 2 3]
print("z=", z) # [0 1 2 3]
z = rnadome..
z = 0.5
m = Z.flat[np.abs(Z-z).argmin()]
prnit(m)
Numpy 다차원 배열 재구성
Shape 변경
np.arange(6).reshape(2, 3)
np.arange(6).reshape(2, -1)
# -1이 들어가면 -1 아닌 다른 axis 기준으로 먼저 설정후 남은거 배치
# 즉, axis0을 2로, 나머지는 낑겨넣어
np.arange(6).reshape(-1, 3)
np.arange(24).reshape(3, 2, 4)
np.arange(24).reshape(3, 2, -1)
np.arange(24).reshape(3, -1, 4)
np.arange(24).reshape(-1, 2, 4)
Shape 변경: 일차원>다차원, 다차원>일차원, 다차원>다차원
a = np.arange(6).reshape(2, 3)
a.reshape(6) # [0 1 2 3 4 5]
a.reshape(6,) # [0 1 2 3 4 5]
a.reshape(-1) # [0 1 2 3 4 5]
a.reshape(-1,) # [0 1 2 3 4 5]
a = np.arange(24).reshape(3, 2, 4) # 3*2*4 배열을 1차원 변경
a.reshape(-1,)
a.reshape(4, 6) # 4*6배열로 변경
a.reshape(-1, 6)
a.reshape(4, 3, 2) # 배열 원소 순서를 잘 보길 바랍니다.
a = np.arange(24).reshape(3, 2, 4) # 3차원 배열
b = a.reshape(2, -1) # a를 2차원 배열로 변경
b[1, 3] = 100 # b의 원소 변경
print(id(a), id(b)) # 다른 주소 != 다른 객체. b는 a의 view.
print(a, b)
print(a[1, 1, 3]) # 100
# a, b 모두에서 같은 위치의 원소 변경됨.
ravel(), flatten()
- ravel(): 원 배열의 view를 1d array로 return
- flatten(): 원 배열의 복사본을 1d array로 return
a = np.arange(6).reshape(2, 3)
b = a.ravel()
print(b) # [0 1 2 3 4 5]
c = a.flatten()
print(c) # [0 1 2 3 4 5]
a[0,0] = 10
print(a, b, c)
# a와 b는 바뀌고 c는 안바뀜
tile()
- 주어진 배열을 반복해서 새 배열 만들어 return
np.tile(np.arange(3), 3) # arnage(3)을 3개 붙여 반환
np.tile(np.arange(3), (3.2)) # tuple 지정 가능, axis0*3회, 1*2회
np.tile(np.arange(5).reshape(2, 3), 3) # 다차원 배열 반복 가능.
# 가장 마지막 배열, axis 1방향으로 3번 반복.
np.tile(np.arange(6).reshpae(2,3), (3,2))
a = np.arange(6).reshape(2, 3)
b = no.tile(a, (3, 2)) # 동일한 배열만 반복 가능
a[0, 0] = 10
print(b)
stack(), vstack(), hstack()
- tile은 같은 배열만 반복가능하다는 단점 있음
- 얘네들은 다른 배열 붙일 수 있음
- stack: tuple로 지정하는 배열의 shape 같아야 하고, argument로 반환된 배열은 차원이 하나씩 증가함.
- vstack: vertical
- hstack: horizental
- 1차원 배열: 옆으로 원소 통일, 원소의 개수 달라도 문제X
- 다차원: axis 개수 같아야 하며, axis 1 제외한 나머지 axis의 원소 개수 같아야 함. = axis 1 뒤에 쭉 이어붙는다는 거.
# stack
a = np.arange(3)
b = np.arange(3, 6)
c = np.stack((a, b))
# a, b를 붙임
print(c)
print(c.shape) # (2, 3)
d = np.arange(10, 16).reshape(2, 3)
# 3차원 배열 만들기
e = np.stack((c, d), axis=0)
# axis0 주면, 원래 배열의 axis 0,1이 새 배열의 axis 0,1이 됨
print(e.shape) # (2, 2, 3): 0번 axis방향으로 나란히 놓임
f = np.stack((c, d), axis=1)
print(f.shape) # (2, 2, 3)
g = np.stack((c, d), axis=2)
print(g.shape) # (2, 3, 2)
# hstack: horizental stack-옆으로 이어붙여
# 1차원 배열
h1 = np.hstack((np.array([1. 2]), np.array([3, 4])))
print(h1)
print(h1.shape)
h2 = np.hstack((np.array([1, 2, 3]), np.array([4, 5)))
print(h2)
print(h2.shape)
h3 = np.hstack((np.array([1, 2, 3]), np.array([4, 5]), np.array([6, 7, 8, 9])))
print(h3)
print(h3.shape) # (9,)
# np.array대신 tuple로 이어붙인 list 형식
h4 = np.hstack(([1, 2], [3, 4]))
print(h4)
print(h4.stack)
h5 = np.hstack((c,d))
print(c)
print(d)
print(c.shape)
print(d.shape)
print(h5)
print(h5.shape)
# hstack 다차원 배열
aa = np.arange(24).reshape(2, 3, 4)
bb = np.arange(32).reshape(2, 4, 4)
h6 = np.hstack((aa, bb))
print(aa.shape) # (2, 3, 4)
print(bb.shape) # (2, 4, 4)
print(h6.shape) # (2, 7, 4): axis 1방향으로 붙음
# vstack: vertical stack-아래로 이어붙여
aa = np.arange(24).reshape(2, 3, 4)
bb = np.arange(24, 60).reshape(3, 3, 4)
h8 = np.vstack((aa, bb)) # axis 0방향 원소가 달라도 ok
print(h8)
print(h8.shape) # (5, 3, 4)
Numpy 다차원 배열의 속성 변경
n = np.arange(5)
print(n.dtype) # int32
n[0] = 5
print(n, n.dtype) # [5 1 2 3 4] int32
n[2] = 10.8
print(n, n.dtype) # [5 1 10 3 4] int32: 소수점 뒤 썰림
m = n.astype(np.int64)
print(m, m.dtype) # [5 1 10 3 4] int64
print(n, n.dtype) # [5 1 10 3 4] int32
f = n.astype(np.float64)
print(f, f.dtype) # [5. 1. 10. 3. 4.] float64
c = n.astype(np.complex128)
print(c, c.dtype) # [5.+0.j 1.+0.j 10.+0.j 3.+0.j 4.+0.j] complex128
print(n.dtype) # int32
n.flags.writeable = False
n[0] = 10 # valueErrro: assignment destination is read-only
Numpy 다차원 배열 변수와 할당 연산자
import numpy as np
x = np.arange(5)
print(x) # [0 1 2 3 4]
print(id(x)) # ip a
x += 1
print(x) # [1 2 3 4 5]
print(id(x)) # ip a: 변경 전과 같은 address
x = np.arange(5)
print(x) # [0 1 2 3 4]
print(id(x)) # ip a
x = x + 1
print(x) # [1 2 3 4 5]
print(id(x)) # ip b: 변경 전과 다른 address
import numpy as np
def add1(x):
x += 1
a = np.arange(5)
print(a) # [0 1 2 3 4]
add1(a) # 함수가 먹힘
print(a) # [1 2 3 4 5]
def add2(x):
x = x + 1
a = np.arange(5)
print(a) # [0 1 2 3 4]
add2(a) # 함수가 안먹힘.return문 없고 다른 객체 반환하기 때문
print(a) # [0 1 2 3 4]
Broadcasting
- shape이 다른 두 개의 ndarray들을 이용, 산술연산을 할 때 numpy가 ndarrays를 처리하는 방법
shape이 같은 두 ndarray의 산술연산
- 원소끼리 연산이 이루어짐
a = np.array([1, 2, 3])
b = np.array([10, 20, 30])
a + b # arrray([10, 22, 33])
a * b # arrray([10, 40, 90])
a = np.arange(12).reshape(3, 4) # 0 ~ 11까지
b = np.arange(10, 22).reshape(3, 4) # 10 ~ 21까지
a + b # array 각 대응 원소끼리 연산, 10 ~ 32까지
a = np.array([1, 2, 3])
b = np.array([1, 2])
a + b # ValueError: operands could not be broadcast together with shapes..
ndarray와 상수의 산술 연산
x = np.arange(1, 5)
print(x) # [1 2 3 4]
print(x + 3) # [4 5 6 7]
print(x * 3) # [3 6 9 12]
print(x / 3) # [0.3333 0.66667 1. 1.33333]
x = np.arange(1, 7).reshape(2, 3)
print(x + 3) # [[4 5 6] [7 8 9]]
print(3 * x) # [[3 6 9] [12 15 18]]
Shape이 서로 다른 두 ndarray의 산술 연산
axis의 원소의 갯수가 다른 두 ndarray의 산술 연산
a = np.arange(1, 7).reshape(2, 3)
b = np.array([[1, 2, 1]])
print(a + b) # [[2 4 4] [5 7 7]]
c = np.array([1, 2])
print(a + b) # ValueError: operands could not be broadcast together with shapes..
a = np.arange(1, 7).reshape(2, 3)
b = np.array(([1], [2]])
print(a + b) # [[2 3 4] [6 7 8]]
c = np.array([[1, 1], [2, 2]])
print(a + b) # ValueError: operands could not be broadcast together
a = np.arange(1, 9).reshape(2, 4)
b = np.array([[1, 1], [2, 2]])
print(a + b) # ValueError: operands could not be broadcast together
a = np.arange(1, 25).reshape(2, 3, 4)
b = np.array([1, 2, 1, 2])
print(a + b) # 계산이 된다?
a = np.arange(21, 25).reshape(2, 3, 4)
b = np.arange(8).reshape(2, 1, 4)
print(a + b) # 계산이 된다!
a = np.array([1, 2, 3]).reshape(3, 1)
b = np.array([1, 2, 1]).reshape(1, 3)
print(a + b) # 계산이 되네
728x90
'컴퓨터 > 프로그래밍' 카테고리의 다른 글
[Python] 파이썬 기초 12: Matplotlib (3) | 2024.09.06 |
---|---|
[Python] 파이썬 기초 11: Numpy(5, 6) (0) | 2024.09.06 |
[Python] 파이썬 기초 9: Numpy(1, 2) (1) | 2024.09.05 |
[Python] 파이썬 기초 8: 함수(3, 4) (1) | 2024.09.04 |
[Python] 파이썬 기초 7: 함수(1, 2) (0) | 2024.09.04 |