기본 콘텐츠로 건너뛰기

[ML] 결정트리(Decision Tree) 모델

[python] 리스트(List)

리스트(List)

내용

리스트(List)

리스트(list)의 특성은 다음과 같습니다.

리스트(list)
  • 대괄호([ ]) 내에 자료들을 입력
  • 입력된 자료가 없는 빈 리스트 객체 생성 가능
  • 숫자형와 문자형을 혼합하여 가질 수 있음
  • 요소로 다른 리스트를 가질수 있음
  • 요소의 수정이 가능 즉, 가변(mutable) 객체

다음 코드로 생성된 리스트 객체 ls1, ls2, 그리고 ls3은 각각 수치형, 문자형, 그리고 두 자료형의 혼합으로 구성되어 있습니다.

lst1=[2, 1, 5];lst1
[2, 1, 5]
lst2=['a', 'python', 'kotlin'];lst2
['a', 'python', 'kotlin']
lst3=[23, "computer", 98, "apple"];lst3
[23, 'computer', 98, 'apple']

객체 ls4는 리스트내에 다른 리스트를 요소로 포함하고 있습니다.

lst4=[1, ["car", "computer"], 2,["apple, pear"]];lst4
[1, ['car', 'computer'], 2, ['apple, pear']]

리스트는 가변객체(mutable)

리스트는 1개 이상의 요소를 가지며 각 요소에 순차적으로 인덱스가 자동으로 할당됩니다. 그러므로 문자열과 같이 리스트 역시 시퀀스 객체이며 그 인덱스를 사용하여 특정한 요소에 접근할 수 있습니다. 또한 가변 객체인 리스트의 각 요소는 그 인덱스를 사용하여 수정, 치환, 삭제 할 수 있습니다.

lst1[0], lst1[-3]
(2, 2)
lst1[2], lst1[-1]
(5, 5)

리스트내에 다른 리스트가 내재되어 있을 경우는 식 1과 같이 첫번째 리스트의 인덱스와 내재된 리스트의 인덱스를 연이어 사용합니다.

객체이름[첫번째리스트의 인덱스][두번째리스트의 인덱스]...(식 1)
lst4=[1, ["car", "computer"], 2,["apple, pear"]]; lst4
[1, ['car', 'computer'], 2, ['apple, pear']]
lst4[1]
['car', 'computer']
lst4[1][1]
'computer'

리스트 객체의 인덱스와 슬라이싱 규칙을 적용하여 요소를 수정할 수 있습니다.

lst4[0]=100
lst4
[100, ['car', 'computer'], 2, ['apple, pear']]
lst4[1][1]='노트북'
lst4
[100, ['car', '노트북'], 2, ['apple, pear']]
x=[1,2,3,4,5,6,7]
x[:3]=[10, 20, 30]
x
[10, 20, 30, 4, 5, 6, 7]

슬라이싱 규칙의 형식 [::-1]를 사용하여 리스트의 요소들을 역순서로 재배치 할 수 있습니다.

x=[1,2,3,4,5,6,7]
x1=x[::-1]
x1
[7, 6, 5, 4, 3, 2, 1]

리스트 객체의 복사

리스트는 변경가능한 가변객체 입니다. 할당연산자("=")를 사용하여 리스트 객체를 복사할 경우 얕은 복사(shallow copy)가 이루어집니다. 즉, 객체 b와 a는 같은 참조점을 가지며 서로 연결(상호참조)되어 한 객체의 변화는 다른 객체의 변화를 일으킵니다.

a=[20, 5, 1]
b=a
b==a
True
b is a
True
b[0]='a'
a, b
(['a', 5, 1], ['a', 5, 1])

다음 코드에 사용한 메소드 x.append(y)는 객체 x의 마지막에 요소 y를 첨가합니다. 이 메소드는 리스트를 포함한 가변 컬렉션 객체에 공통을 적용됩니다.

a.append('c')
a, b
(['a', 5, 1, 'c'], ['a', 5, 1, 'c'])

위 코드에서 객체 b는 객체 a 자체를 할당한 것으로 동일한 참조점을 갖습니다. 그러므로 객체 a 또는 b 두 객체 중 하나의 객체가 수정되거나 새로운 요소가 보충되면 다른 객체 역시 수정됩니다. 즉, 얖은 복사가 이루어집니다.

다음과 같이 객체 b1에 슬라이싱을 적용하여 객체 a1의 각 요소를 직접 할당하면 두 리스트 객체는 연결되지 않으므로 상호 영향을 줄 수 없는 깊은복사(deep copy)가 실행됩니다. 즉, 객체 b1은 리스트 객체인 a1을 참조하는 것이 아니라 그 객체의 각 요소를 참조합니다. 그러므로 b1의 참조 대상이 달라지는 것은 a1에 영향을 주지 못합니다. 물론 반대의 경우 역시 서로 영향을 주지 않습니다.

a1=[20, 5, 1]
b1=a1[:]
b1
[20, 5, 1]
a1==b1, a1 is b1
(True, False)
id(a1),id(b1)
(1583889740288, 1583889740032)

위 결과와 같이 두 객체 a1, b1은 같은 값이지만 다른 참조점을 가리키므로 다른 객체입니다. 그러나 다음 결과와 같이 각 요소에 대한 참조점은 같습니다.

print(a1[0] is b1[0])
print(a1[1] is b1[1])
print(a1[2] is b1[2])
True
True
True

위 코드들의 결과인 리스트의 얕은 복사와 깊은 복사를 시각화하면 그림 1과 같습니다.

그림 1. 리스트의 (a)얕은 복사와 (b)깊은 복사.

그림 1(b)의 깊은 복사에서 나타낸 것과 같이 객체 a1과 b1은 같은 요소들을 가진 다른 객체이므로 한 객체의 변화는 다른 객체에 영향을 주지 못합니다.

b1[0]='a'
a1, b1
([20, 5, 1], ['a', 5, 1])

즉, a1과 b1은 값은 같지만 다른 참조점을 갖음을 의미합니다. 위와 같이 인덱스를 사용하여 깊은 복사를 수행하는 과정은 리스트 메소드인 .copy를 사용하여 달성할 수 있습니다. 다음 객체 a는 요소로 다른 리스트를 갖는 객체입니다. 다음 코드에서 b는 a에 대한 깊은 복사를 실시합니다. 즉, a의 각 요소를 참조한 것입니다. 이 경우 b는 a의 요소인 내재된 리스트인 [10, 20]을 참조하는 것으로 이 리스트에 대한 복사는 얕은복사가 실행됩니다.

a=[1, [10,20]]
b=a.copy()
b
[1, [10, 20]]

리터럴인 첫 번째 요소는 깊은 복사가 이루어 집니다.

b[0]=3 
b, a
([3, [10, 20]], [1, [10, 20]])

그러나 a의 두 번째 요소인 리스트의 복사과정은 좀 더 복잡합니다. 객체 b는 내재된 리스트의 각 요소가 아니라 리스트 자체를 복사한 것으로 그림 1(a)와 같이 이루어집니다. 즉, 얕은 복사가 이루어 집니다.

b[1][0]=0.1 
b, a
([3, [0.1, 20]], [1, [0.1, 20]])
a==b
True
a is b
False

위 결과와 같이 객체 a와 b의 깊은 복사가 이루어지지만 내재된 리스트의 경우 다음 코드의 결과와 같이 앝은 복사가 이루어집니다.

a[1] is b[1]
True
a[1][0]=1000
a, b
([1, [1000, 20]], [1, [1000, 20]])

객체의 복사를 위해 특정된 copy 모듈의 함수들을 사용할 수 있습니다. 이 모듈의 copy() 함수는 위와 동일한 결과를 반환하지만 다른 함수 deepcopy()는 내재된 리스트 객체에 대해서도 깊은 복사를 실행합니다.

import copy
a=[1, [10,20]]
b=copy.copy(a)
b
[1, [10, 20]]

한 객체에서 리털러인 첫번째 요소의 변화는 다른 객체의 영향은 없습니다. 즉, 깊은 복사를 시행합니다.

a[0] is b[0]
True
a[1][0] is b[1][0]
True
b[0]='7'
a, b
([1, [10, 20]], ['7', [10, 20]])

그러나 리스트 객체인 두 번째 요소의 경우는 객체 상호간에 영향을 주는 얕은 복사가 실행됩니다. 즉, copy() 함수는 .copy() 메소드와 정확히 같은 결과를 반환합니다.

b[1][0]='x'
a, b
([1, ['x', 20]], ['7', ['x', 20]])

copy.deepcopy() 함수는 내재된 리스트에 대해 깊은 복사를 실행합니다.

c=copy.deepcopy(a)
c, a
([1, ['x', 20]], [1, ['x', 20]])
c[0]="deep"
a, c
([1, ['x', 20]], ['deep', ['x', 20]])
c[1][1]='copy'
a, c
([1, ['x', 20]], ['deep', ['x', 'copy']])

위에서 소개한 리스트 객체의 복사는 다른 수정가능한 컬렉션인 사전형에도 적용됩니다.

a=[1, {'ten': 'Ten', 'two': 2}]
bc=copy.deepcopy(a)
c
[1, {'ten': 'Ten', 'two': 2}]
c[1]['ten']=10
c
[1, {'ten': 10, 'two': 2}]
a
[1, {'ten': 'Ten', 'two': 2}]

리스트의 대표적인 메소드

리스트 객체 역시 클래스로 작성되었습니다. 그러므로 리스트 객체 내에서만 작동하는 고유한 속성과 메서드를 포함하고 있으며 그 중 사용 빈도가 높은 대표적인 메소드를 표 1에 수록하였습니다.

다른 컬렉션인 튜플, 사전, 그리고 집합형 역시 클래스로 작성되었으므로 각각 고유한 속성과 메서드를 가집니다. 그러나 같은 이름의 속성과 메서드들로 존재하는 경우가 많아 표 1에서 소개하는 메소드들의 대부분이 다른 컬렉션 자료형에서도 작동합니다. 물론 이러한 공통 작동에는 클래스 상속 등 다양한 작동 기전이 작용하지만 일부 속성과 메서드들의 이름이 같다고 인식하는 것으로 충분합니다. 각 객체에 대해 dir() 함수를 적용하여 고유한 속성과 메서드를 확인할 수 있습니다.

표 1 리스트 메서드와 연산자
메소드 내 용
x.append(y)리스트 x의 마지막에 요소 y를 첨가
첨가되는 요소의 자료형이 유지
x.extend(y) 리스트 x에 마지막 요소 다음에 y를 첨가
y는 리스트등의 컬렉션이며 그 자료형은 유지되지 않음
'+' 연산자 두 리스트를 결합
이 연산은 위의 extend() 메서드와 같은 결과를 반환
'*' 연산자 리스트의 반복
x.insert(ind, val)객체 x에서 지정한 인덱스 위치(ind)에 값(val)을 삽입
인수 ind는 정수이어야 합니다. 즉, 삽입할 위치는 1개 이어야 합니다.
del x, del x[ind] 키워드 del을 사용하여 객체 x 또는 지정한 인덱스의 요소를 삭제
x.remove(val) 객체 x에 존재하는 요소 val을 삭제, val은 존재해야 합니다.
x.pop(ind) 객체 x내 지정한 인덱스(ind)에 해당하는 요소를 삭제
ind가 없을 경우 마지막 요소를 제거
x.clear() 객체 x의 모든 요소들을 제거
x=[], x[index]=[] 객체 x의 원하는 인덱스(index)에 빈 리스트를 할당함으로서 삭제 할 수 있음
x.count(y) 객체 x의 요소들 중에 y의 갯수를 반환합니다.
x.index(y)객체 x의 요소들 중에 y의 index를 반환합니다.
위 두 메서드 모두 y가 여러개일 경우 처음의 index만을 반환합니다.

다음은 인덱스를 사용하여 리스트 객체의 요소를 호출하는 예로서 대응하는 요소가 없을 경우 예외(에러)가 발생합니다.

x=[1,2,3]
x[3]
IndexError: list index out of range

리스트 객체의 마지막에 요소를 첨가하기 위해서는 .append().extend() 메소드를 적용합니다. 이 두 메소드의 차이는 첨가하는 객체의 자료형의 유지 여부에 있습니다.

x.append(4); x
[1, 2, 3, 4]
x.append([5]); x
[1, 2, 3, 4, [5]]

위 코드와 같이 .append()의 경우는 첨가되는 객체의 자료형은 유지 됩니다. 그러나 다음 코드의 결과와 같이 x.extend(y)는 객체 y 자체가 아닌 y의 각 요소가 호출되어 리터럴으로서 객체 x에 삽입되므로 y의 자료형은 잃어버립니다. 이 메소드의 인수 객체 y는 요소 각각을 호출할 수 있는 이터러블 객체(iterable)입니다. 그러므로 숫자 리터럴(하나의 숫자)은 실행되지 않습니다.

y=['a','b','c']
x.extend(y); x
[1, 2, 3, 4, 'a', 'b', 'c']
x.extend(6); x
TypeError: 'int' object is not iterable

산술 연산자 +와 *는 리스트 객체들을 대상으로 다른 연산을 실행합니다. 즉, + 연산자는 두 리스트의 결합, 그리고 * 연산자는 리스트 객체의 반복을 위해 사용합니다.

x=[1,2,3]
y=[4,5]
x+y
[1, 2, 3, 4, 5]
3*x
[1, 2, 3, 1, 2, 3, 1, 2, 3]

리스트 객체의 지정된 위치에 값을 삽입하기 위해 .insert(index, value)을 적용합니다.

x=[1,2,3]
x.insert(1, 4); x
[1, 4, 2, 3]

이 메소드는 다음과 같이 컬렉션 자료형을 사용하여 여러 개의 값들을 전달할 수 있지만 지정을 위한 인덱스는 정수(스칼라)이어야 합니다. 다음 코드의 첫 번째 인수인 [2, 3]은 리스트로서 인덱스로 지정할 수 없습니다.

x.insert([2,3], [20, 24])
~~ TypeError: 'list' object cannot be interpreted as an integer
x.insert(3, [20, 24])
x
[1, 4, 2, [20, 24], 3]

다음은 리스트 뿐만 아니라 파이썬으로 작성된 모든 객체나 객체의 요소를 제거하기 위한 다양한 키워드, 메소드들에 대한 예입니다(표 3.2.1).

x=[1, 4, 12, 21, 33, 2, 3]
del x[2]; x
[1, 4, 21, 33, 2, 3]
x.remove(1); x
[4, 21, 33, 2, 3]
x.pop(2) #제거되는 원소를 반환 
33
x.pop() #마지막 원소 제거 
3
x
[4, 21, 2]
x.clear()
x
[]

요소가 없는 빈 리스트도 객체입니다. 그러므로 다음 코드와 같이 빈 리스트를 할당하여 요소(들)을 삭제할 수 있습니다.

x=[1, 4, 12, 21, 33, 2, 3]
x[1]=[];x
[1, [], 12, 21, 33, 2, 3]
x[3:6]=[]; x
[1, [], 12, 3]
x=[]; x
[]

.count()를 사용하여 리스트 내의 특정한 요소의 갯수를 확인합니다.

x=[1,2,1,1,2,4,5,5]
x.count(1)
3

.index()를 사용하여 지정한 인덱스에 대응하는 값을 확인합니다.

x.index(4)
5

리스트 객체는 하나이상의 요소들로 구성되어 있으며 각 요소의 자료형은 이질적인 것일 수 있습니다. 그러므로 요소 하나를 호출할 경우 그 요소의 자료형을 유지하지만 슬라이싱에 의해 두 개 이상의 요소들을 호출할 경우 리스트가 됩니다.

a=[1,2,'리스트', [3,4]]
a[0]
1
type(a[2])
str
a[0:2]
[1, 2]
type(a[0:2])
list

댓글

이 블로그의 인기 게시물

[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' 와 같

[matplotlib] 히스토그램(Histogram)

히스토그램(Histogram) 히스토그램은 확률분포의 그래픽적인 표현이며 막대그래프의 종류입니다. 이 그래프가 확률분포와 관계가 있으므로 통계적 요소를 나타내기 위해 많이 사용됩니다. plt.hist(X, bins=10)함수를 사용합니다. x=np.random.randn(1000) plt.hist(x, 10) plt.show() 위 그래프의 y축은 각 구간에 해당하는 갯수이다. 빈도수 대신 확률밀도를 나타내기 위해서는 위 함수의 매개변수 normed=True로 조정하여 나타낼 수 있다. 또한 매개변수 bins의 인수를 숫자로 전달할 수 있지만 리스트 객체로 지정할 수 있다. 막대그래프의 경우와 마찬가지로 각 막대의 폭은 매개변수 width에 의해 조정된다. y=np.linspace(min(x)-1, max(x)+1, 10) y array([-4.48810153, -3.54351935, -2.59893717, -1.65435499, -0.70977282, 0.23480936, 1.17939154, 2.12397372, 3.0685559 , 4.01313807]) plt.hist(x, y, normed=True) plt.show()

R 미분과 적분

내용 expression 미분 2차 미분 mosaic를 사용한 미분 적분 미분과 적분 R에서의 미분과 적분 함수는 expression()함수에 의해 생성된 표현식을 대상으로 합니다. expression expression(문자, 또는 식) 이 표현식의 평가는 eval() 함수에 의해 실행됩니다. > ex1<-expression(1+0:9) > ex1 expression(1 + 0:9) > eval(ex1) [1] 1 2 3 4 5 6 7 8 9 10 > ex2<-expression(u, 2, u+0:9) > ex2 expression(u, 2, u + 0:9) > ex2[1] expression(u) > ex2[2] expression(2) > ex2[3] expression(u + 0:9) > u<-0.9 > eval(ex2[3]) [1] 0.9 1.9 2.9 3.9 4.9 5.9 6.9 7.9 8.9 9.9 미분 D(표현식, 미분 변수) 함수로 미분을 실행합니다. 이 함수의 표현식은 expression() 함수로 생성된 객체이며 미분 변수는 다음 식의 분모의 변수를 의미합니다. $$\frac{d}{d \text{변수}}\text{표현식}$$ 이 함수는 어떤 함수의 미분의 결과를 표현식으로 반환합니다. > D(expression(2*x^3), "x") 2 * (3 * x^2) > eq<-expression(log(x)) > eq expression(log(x)) > D(eq, "x") 1/x > eq2<-expression(a/(1+b*exp(-d*x))); eq2 expression(a/(1 + b * exp(-d * x))) > D(eq2, "x") a * (b * (exp(-d * x) * d))/(1 + b