기본 콘텐츠로 건너뛰기

벡터와 행렬에 관련된 그림들

[numpy] 인덱스와 슬라이싱(Index & Slicing)

인덱스와 슬라이싱(index & slicing)

배열차원그차원의 인덱스를 참조할 수 있습니다.

인덱스

numpy의 자료형인 배열(array)은 리스트들로 구성됩니다. 객체 a와 같이 한개의 리스트 작성된 경우를 벡터(vector)라고 합니다.

다음 코드의 랜덤수 생성은 랜덤수 생성을 위한 numpy 함수들 참조

np.random.seed(10)
a=np.random.randint(0, 11, size=10)
a
array([ 9,  4,  0,  1,  9,  0,  1, 10,  8,  9])
print(f"a의 차원,:{a.ndim}, a의 모양{a.shape}")
a의 차원,:1, a의 모양(10,)

위 결과와 같이 객체 a는 1차원으로 10개의 요소를 포함합니다. 벡터는 1차원이므로 1개의 축만이 존재하므로 객체의 모양은 "크기,"와 같이 숫자 한개로 표시됩니다.

리스트는 최왼쪽부터 0으로 시작되는 음이 아닌 정수인 인덱스를 가집니다(문자열의 인덱스 참조). 배열 역시 리스트로 구성되므로 같은 형태의 인덱스를 가집니다(표 1).

표 1 객체 a(벡터)의 인덱스
요소9 4 0 1 9 0 1 10 8 9
인덱스0 1 2 3 4 5 6 7 8 9
역인덱스-10 -9 -8 -7 -6 -5 -4 -3 -2 -1

표 1에서 나타낸 것과 같이 인덱스(index)는 최왼쪽의 요소부터 시작하는 음이 아닌 정수이며 역으로 마지막 요소를 -1로 시작하는 음의 정수를 인덱스로 사용할 수 있습니다. 이를 역인덱스(inverse index)라고 합니다.

표1의 형식으로 인덱스를 사용하여 지정한 위치의 값을 호출하거나 수정할 수 있습니다.

객체이름[인덱스](식 1)
a[2]
0
a[2]=123; a
array([  9,   4, 123,   1,   9,   0,   1,  10,   8,   9])

2차원인 행렬(matrix)의 경우는 두 개의 축을 가집니다. 다음 객체 A는 2개의 리스트로 구성된 행렬입니다.

np.random.seed(3)
A=np.random.randint(0, 10, size=(2,5))
A
array([[8, 9, 3, 8, 8],
       [0, 5, 3, 9, 9]])
print(f"A의 차원,:{A.ndim}, A의 모양{A.shape}")
A의 차원,:2, A의 모양(2, 5)

위 객체 A는 2차원이므로 두 개의 축이 필요합니다. 이것은 이 객체의 모양이 두개의 숫자로 이루어진 것으로 알 수 있습니다. 표 2는 이 객체를 나타낸 것으로 가로방향을 행(row)축, 세로방향을 열(column)축으로 나타냅니다.

표 2 객체 A(행렬)
0 열 1 열 2 열 3 열 4 열
0 행 8 9 3 8 8
1 행 0 5 3 9 9

표 2와 같이 객체 A의 각 요소는 행과 열의 인덱스를 가집니다. 예를 들어 0행과 0열에 위치한 요소는 8이 됩니다. 즉, 8의 인덱스는 (0, 0)이 되며 첫번째 인덱스는 행, 두번째 인덱스는 열을 나타냅니다. 그러므로 행렬의 요소를 호출하거나 수정하기 위해서는 행과 열의 인덱스들을 모두 적용해야 합니다(식 2).

객체이름[행인덱스, 열인덱스](식 2)
A[0,0]
8
A[1, 0]=100
A
array([[  8,   9,   3,   8,   8],
       [100,   5,   3,   9,   9]])

다음 객체 B는 3차원으로 두 개의 행렬을 연결한 것입니다.객체.shape의 결과는 3개의 숫자로 반환됩니다.

np.random.seed(3)
B=np.random.randint(0, 10, size=(2, 2,5))
B
array([[[8, 9, 3, 8, 8],
        [0, 5, 3, 9, 9]],

       [[5, 7, 6, 0, 4],
        [7, 8, 1, 6, 2]]])
print(f"B의 차원,:{B.ndim}, B의 모양{B.shape}")
B의 차원,:3, B의 모양(2, 2, 5)

위 결과와 같이 B는 3차원이며 모양은 3개의 수들로 구성되며 각 수 역시 인덱스가 부여됩니다. 이 인덱스를 축인덱스(axis index)라고 하며 numpy의 배열에 적용할 수 있는 많은 함수나 메서드의 인수 axis에 전달하는 값이 됩니다. 이 축인덱스는 다음과 같이 나타낼 수 있습니다.

축인덱스3 2 1
모양2 2 5

그러므로 식 1과 식 2를 일반화하여 나타내면 식 3과 같습니다.

객체이름[n차원인덱스, …, 2차원(행)인덱스, 1차원(열)인덱스](식 3)
B[1,0,1]
7

슬라이싱

식 3은 인덱스를 사용하여 한 개의 요소를 호출할 수 있지만 식 4와 같이 여러 인덱스들의 조합을 적용하여 하나 이상의 요소들을 호출하거나 수정할 수 있습니다. 물론 새로운 객체를 생성할 수 있습니다.

객체[인덱스1: 인덱스2:인덱스 간격](식 4)
(인덱스1) ~ (인덱스2)-1 중에 지정한 간격에 대응하는 요소를 호출
간격의 기본값은 1이며 생략가능
인덱스1을 생략하면 0으로 인식
위 구문은 각 축에 별도로 지정, 2차원인 경우
객체[행인덱스1: 행인덱스2, 열인덱스1: 열인덱스2]

위 식 4는 1개 이상의 요소를 호출하는 경우로 슬라이싱(slicing)이라고 합니다. 물론 인덱스 1개일 경우는 대응하는 요소는 1개이며 그 호출된 결과의 자료형은 요소 자체의 리터럴자료형(숫자형 또는 문자형)이 됩니다. 반면에 두개 이상의 요소를 호출한 결과는 배열이 됩니다.

np.random.seed(3)
A=np.random.randint(0, 10, size=(3,5))
A
array([[8, 9, 3, 8, 8],
       [0, 5, 3, 9, 9],
       [5, 7, 6, 0, 4]])
A[0,1], type(A[0,1])
(9, numpy.int32)
A[0:3,2]
array([3, 3, 6])

표 3은 행렬 객체에서의 슬라이싱 규칙을 나타내고 있습니다. 이 규칙은 차원 인덱스를 고려하면 모든차원의 배열에 적용됩니다.

표 3 행렬의 슬라이싱(Slicing) 규칙
규칙내용
A[r, c] r 번째 행과 c 번째 열의 값
A[r1:rn:간격, c1:cn:간격]식 1.1.7을 행과 열 각각에 적용.
이 경우 행과 열의 인덱스 갯수는 같아야 함
A[::-1, ::-1]행과 열 모두 역순으로 정렬
A[ :, :] 콜론(:)은 각 행과 열의 모든 범위를 의미
A[-1,-1]마지막행과 열의 요소.
인덱스에서 음(-) 값은 뒤 쪽을 나타냄.
x=np.array([9, 2, 1, 3, 8, 3, 6, 7])
x
array([9, 2, 1, 3, 8, 3, 6, 7])
x[::-1]
array([7, 6, 3, 8, 3, 1, 2, 9])
x[::2]
array([9, 1, 8, 6])
np.random.seed(5)
x=np.random.randint(10, size=(2,2))
x
array([[3, 6],
       [6, 0]])
x[::-1, :]
array([[6, 0],
       [3, 6]])
x[:,::-1]
array([[6, 3],
       [0, 6]])
x[::-1,::-1]
array([[0, 6],
       [6, 3]])

슬라이싱을 위해 정수와 콜론(:)을 사용하는 방법 외에 불리언 (boolean)으로 실행 할 수 있습니다.

np.random.seed(9)
x=np.random.randint(30, size=(10))
x
array([28, 21, 22, 24, 27, 22, 29,  1, 22, 20])

연산자 %는 나머지를 반환합니다.

x%3==0
array([False,  True, False,  True,  True, False, False, False, False,
       False])

다음 코드는 객체 x의 각 요소를 3으로 나누어지는 수만으로 구성

x[x%3==0]
array([21, 24, 27])

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같...

[sympy] Sympy객체의 표현을 위한 함수들

Sympy객체의 표현을 위한 함수들 General simplify(x): 식 x(sympy 객체)를 간단히 정리 합니다. import numpy as np from sympy import * x=symbols("x") a=sin(x)**2+cos(x)**2 a $\sin^{2}{\left(x \right)} + \cos^{2}{\left(x \right)}$ simplify(a) 1 simplify(b) $\frac{x^{3} + x^{2} - x - 1}{x^{2} + 2 x + 1}$ simplify(b) x - 1 c=gamma(x)/gamma(x-2) c $\frac{\Gamma\left(x\right)}{\Gamma\left(x - 2\right)}$ simplify(c) $\displaystyle \left(x - 2\right) \left(x - 1\right)$ 위의 예들 중 객체 c의 감마함수(gamma(x))는 확률분포 등 여러 부분에서 사용되는 표현식으로 다음과 같이 정의 됩니다. 감마함수는 음이 아닌 정수를 제외한 모든 수에서 정의됩니다. 식 1과 같이 자연수에서 감마함수는 factorial(!), 부동소수(양의 실수)인 경우 적분을 적용하여 계산합니다. $$\tag{식 1}\Gamma(n) =\begin{cases}(n-1)!& n:\text{자연수}\\\int^\infty_0x^{n-1}e^{-x}\,dx& n:\text{부동소수}\end{cases}$$ x=symbols('x') gamma(x).subs(x,4) $\displaystyle 6$ factorial 계산은 math.factorial() 함수를 사용할 수 있습니다. import math math.factorial(3) 6 a=gamma(x).subs(x,4.5) a.evalf(3) 11.6 simpilfy() 함수의 알고리즘은 식에서 공통사항을 찾아 정리하...

sympy.solvers로 방정식해 구하기

sympy.solvers로 방정식해 구하기 대수 방정식을 해를 계산하기 위해 다음 함수를 사용합니다. sympy.solvers.solve(f, *symbols, **flags) f=0, 즉 동차방정식에 대해 지정한 변수의 해를 계산 f : 식 또는 함수 symbols: 식의 해를 계산하기 위한 변수, 변수가 하나인 경우는 생략가능(자동으로 인식) flags: 계산 또는 결과의 방식을 지정하기 위한 인수들 dict=True: {x:3, y:1}같이 사전형식, 기본값 = False set=True :{(x,3),(y,1)}같이 집합형식, 기본값 = False ratioal=True : 실수를 유리수로 반환, 기본값 = False positive=True: 해들 중에 양수만을 반환, 기본값 = False 예 $x^2=1$의 해를 결정합니다. solve() 함수에 적용하기 위해서는 다음과 같이 식의 한쪽이 0이 되는 형태인 동차식으로 구성되어야 합니다. $$x^2-1=0$$ import numpy as np from sympy import * x = symbols('x') solve(x**2-1, x) [-1, 1] 위 식은 계산 과정은 다음과 같습니다. $$\begin{aligned}x^2-1=0 \rightarrow (x+1)(x-1)=0 \\ x=1 \; \text{or}\; -1\end{aligned}$$ 예 $x^4=1$의 해를 결정합니다. solve() 함수의 인수 set=True를 지정하였으므로 결과는 집합(set)형으로 반환됩니다. eq=x**4-1 solve(eq, set=True) ([x], {(-1,), (-I,), (1,), (I,)}) 위의 경우 I는 복소수입니다.즉 위 결과의 과정은 다음과 같습니다. $$x^4-1=(x^2+1)(x+1)(x-1)=0 \rightarrow x=\pm \sqrt{-1}, \; \pm 1=\pm i,\; \pm1$$ 실수...