본문 바로가기
  • Hello_
Python/Numpy

[Python] 리스트 (List) vs 넘파이 (Numpy) 어레이 차이

by LDwDL 2023. 2. 12.
728x90
반응형

본 포스팅에서는 리스트와 넘파이 어레이의 차이점에 대해 얘기하고자 합니다.

 

선언

우선 list_ex와 numpy_ex로 리스트와 넘파이 어레이의 예시를 구성해 봅시다.

넘파이 어레이 선언은 리스트를 np.array()로 감싸주면 쉽게 선언이 가능합니다.

import numpy as np

list_ex = [[0,1],[2,3],[4,5]]
numpy_ex = np.array([[0,1],[2,3],[4,5]])

print(list_ex, type(list_ex)) # [[0, 1], [2, 3], [4, 5]] <class 'list'>
print(numpy_ex, type(numpy_ex)) # [[0, 1], [2, 3], [4, 5]] <class 'numpy.ndarray'>

 

출력해 보면 형태는 동일하지만 배열의 형태는 다릅니다.

 

여기서 한 가지 짚고 넘어가야 할 부분은 리스트는 안에 내부 요소의 길이가 달라도 문제는 없지만 넘파이 어레이로 선언될 때는 권장되지 않는 형태입니다.

numpy_ex_asym = np.array([[0],[1,2,3],[4,5]])
"""
C:\Users\AppData\Local\Temp\ipykernel_23804\2631909715.py:1: VisibleDeprecationWarning: 
Creating an ndarray from ragged nested sequences (which is a list-or-
tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, 
you must specify 'dtype=object' when creating the ndarray.
  numpy_ex_asym = np.array([[0],[1,2,3],[4,5]])
"""

print(umpy_ex.dtype) # int32
print(numpy_ex_asym.dtype) # dtype('O')

 

다음과 같이 내부 요소의 길이가 다른 형태는 권장되지 않은 형태이며, 데이터 형태도 정수형태가 아닌 객체(object) 형태로 반환됩니다.

 

사칙연산

리스트의 덧셈은 리스트가 그대로 추가되어 concatenate와 동일한 효과를 가집니다. 

반면에 넘파이 어레이는 우리가 일반적으로 생각하는 바와 같이 내부 요소의 값들이 각각 더해집니다.

list_ex_add = list_ex + list_ex
numpy_ex_add = numpy_ex + numpy_ex

print(list_ex_add) # [[0, 1], [2, 3], [4, 5], [0, 1], [2, 3], [4, 5]]
print(numpy_ex_add)
"""
[[ 0  2]
 [ 4  6]
 [ 8 10]]
"""

 

리스트의 곱셈리스트가 배수만큼 concatenate 되는 것과 동일합니다.

넘파이 어레이의 곱셈은 덧셈과 마찬가지로 값들이 각각 연산이 이뤄집니다.

list_ex_mul = list_ex * 3
numpy_ex_mul = numpy_ex * 3

print(list_ex_mul) # [[0, 1], [2, 3], [4, 5], [0, 1], [2, 3], [4, 5], [0, 1], [2, 3], [4, 5]]
print(numpy_ex_mul)
"""
[[ 0  3]
 [ 6  9]
 [12 15]]
"""

 

뺄셈과 나눗셈은 넘파이 어레이에 모두 적용이 가능하며 위 덧셈과 곱셈과 같이 연산이 이뤄집니다. 하지만 리스트에서는 뺄셈과 나눗셈의 연산은 제공하지 않습니다

numpy_ex_add - numpy_ex
"""
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])
"""

numpy_ex_add / 3
"""
array([[0., 1.],
       [2., 3.],
       [4., 5.]])
"""
list_ex_add - list_ex
"""
TypeError: unsupported operand type(s) for -: 'list' and 'list'
"""

list_ex_mul / 3
"""
TypeError: unsupported operand type(s) for /: 'list' and 'int'
"""

 

위 예시들과 같이 넘파이 어레이는 각 요소들의 연산에 특화되어 있으며, 스칼라 값 혹은 하나의 축이라도 동일한 배열과 연산을 하더라도 자동적으로 크기를 맞춰주어 연산이 이뤄집니다. 이를 'broadcasting'이라고 합니다. 

 

Broadcasting — NumPy v1.24 Manual

Broadcasting The term broadcasting describes how NumPy treats arrays with different shapes during arithmetic operations. Subject to certain constraints, the smaller array is “broadcast” across the larger array so that they have compatible shapes. Broad

numpy.org

 

함수

리스트와 넘파이 어레이에 제공되는 함수는 아주 다양합니다. 다만, 동일한 효과를 가진 함수라도 사용법이 서로 상이합니다.

예를 들어 append의 경우에도 리스트.append()np.append(넘파이)를 활용하며, max의 경우에는 max(리스트)np.max(넘파이) 등과 같이 다릅니다. 

이외에도 많은 함수들을 각각 제공하고 있으니 원하시는 함수가 있으시다면 목적에 맞게 리스트 혹은 넘파이 어레이에 사용될 함수를 선택하시면 됩니다.

 

추가적으로 리스트와 넘파이 어레이의 크기를 반환해 보겠습니다.

print(len(list_ex)) # 3

print(len(numpy_ex)) # 3

print(list_ex.shape)
"""
AttributeError: 'list' object has no attribute 'shape'
"""

print(numpy_ex.shape) # (3, 2)

 

리스트와 넘파이 어레이의 첫 번째 축의 길이는 len()을 통해 반환할 수 있습니다. 하지만 전체 사이즈를 반환하는 shape은 넘파이 어레이만 사용이 가능하며 리스트는 오류가 발생합니다.

 

연산 속도

이는 다른 블로거 분들이 많이 언급을 해주셔서 넘어가고 간단하게 내용만 요약하면, 넘파이 어레이가 리스트에 비해 문법이 간단하고 넘파이 어레이가 벡터화되고 최적화가 되어 있어 빠르다고 합니다. 또한 계산 속도가 빠른 C 코드로 동작하기 때문이라고 합니다.

 

 

728x90
반응형

댓글