달나라 노트

Python numpy : arrary (numpy array 만들기, array의 연산) 본문

Python/Python numpy

Python numpy : arrary (numpy array 만들기, array의 연산)

CosmosProject 2021. 8. 6. 01:45
728x90
반응형

 

 

 

numpy의 array method는 numpy array를 만들어줍니다.

 

 

import numpy as np

arr_1 = np.array([1, 2, 3, 4, 5])
print(arr_1)



-- Result
[1 2 3 4 5]

사용법은 간단합니다.

array method의 인자로서 array로 만들 데이터를 전달해주면 됩니다.

위 예시는 list를 array로 만드는 예시입니다.

 

list 속에 또 다른 list가 없고 단순히 숫자만 존재하므로 1차원 데이터입니다.

 

 

 

import numpy as np

arr_2 = np.array([[1, 2], [3, 4]])
print(arr_2)



-- Result
[[1 2]
 [3 4]]

위 예시도 동일한 형태지만 다른 점은 array로 만들 list에 있습니다.

list 속 list가 존재하죠.

print되는 결과값을 봐도 가장 바깥쪽 큰 list 속에 [1, 2]와 [3, 4]라는 내부 list가 존재합니다.

이러한 데이터를 2차원 데이터라고 합니다.

 

 

 

 

import numpy as np

arr_test = np.array(
    [
        [
            [1, 2, 3],
            [4, 5, 6],
        ],
        [
            [7, 8, 9],
            [10, 11, 12],
        ],
    ]
)
print(arr_test)



-- Result
[[[ 1  2  3]
  [ 4  5  6]]

 [[ 7  8  9]
  [10 11 12]]]

이런식으로 list속의 list를 여러 개 존재하게하여 다중 차원의 array를 만들 수 있습니다.

 

 

 

 

 

 

 

차원에 대해 살짝 더 얘기해봅시다.

보통 1차원이라고 하면 선을 의미합니다. 좀 더 수학적으로 알아듣기 쉽게 얘기한다면 x축만 존재하는(y축이 없는) 그래프라고 보시면 됩니다.

따라서 1차원 좌표를 나타내보면 오로지 x축의 값만 나타내지겠죠.

 

2차원이라고하면 흔히 말하는 x축과 y축이 있는 좌표평면을 생각하면 됩니다.

(1, 2), (3, 5) 이런식으로 x, y값이 표기가되죠.

 

import numpy as np
import pandas as pd


nda_test = np.array(
    [
        [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]
    ]
)
print(nda_test)
print('dimention =', np.ndim(nda_test))



-- Result
[[1 2 3 4 5]
 [1 2 3 4 5]
 [1 2 3 4 5]]
dimention = 2

위 예시를 보면 numpy arrary를 만들 때 가장 바깥쪽 array 속에 여러개의 arrary가 들어가있습니다.

그래서 결과를 보면 가장 바깥쪽 array 안에 1부터 5까지의 값을 가진 array가 총 3개 포함된 형태이죠.

 

여기서 [1, 2, 3, 4, 5]는 하나의 행을 의미한다고 보시면 됩니다.

이게 무슨소린지 더욱 직관적으로 알기 위해 위 array를 pandas의 DataFrame으로 바꿔봅시다.

 

 

import numpy as np
import pandas as pd




nda_test = np.array(
    [
        [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]
    ]
)
print(nda_test)
print('dimention =', np.ndim(nda_test))

pd_test = pd.DataFrame(nda_test)
print(pd_test)



-- Result
[[1 2 3 4 5]
 [1 2 3 4 5]
 [1 2 3 4 5]]
dimention = 2

   0  1  2  3  4
0  1  2  3  4  5
1  1  2  3  4  5
2  1  2  3  4  5

아까와 동일하지만 nda_test라는 2차원 array를 DataFrame으로 바꿔서 출력해봤습니다.

보면 하나의 행에 1부터 5까지의 값이 있는 것이 보이시나요?

즉, 내부 array인 [1, 2, 3, 4, 5]가 하나의 행을 의미하고, 내부 array가 총 3개 있으니 3개의 행이 있는 것입니다.

또 하나의 행에 총 5개의 값이 있으니 컬럼의 개수는 5개이겠지요.

이렇게 2차원 array는 x, y축을 가진 좌표평면(또는 표)라고 볼 수 있습니다.

 

 

 

 

 

import numpy as np
import pandas as pd


nda_test = np.array(
    [
        [1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]
    ]
)
print(nda_test)
print('dimention =', np.ndim(nda_test))

pd_test = pd.DataFrame(nda_test)
print(pd_test)

print(nda_test[1, 3])
print(nda_test[:, 3])
print(nda_test[1, :])



-- Result
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]
 [11 12 13 14 15]]
dimention = 2

    0   1   2   3   4
0   1   2   3   4   5
1   6   7   8   9  10
2  11  12  13  14  15

9
[ 4  9 14]
[ 6  7  8  9 10]

array는 python의 list와 성질이 매우 비슷합니다.

따라서 위처럼 indexing이 가능합니다.

 

다차원 array에선 가장 바깥부터 indexing을 합니다.

또한 indexing은 python의 list와 매우 흡사합니다.

 

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]

nda_test[1, 3]

위같은 array에서 [1, 3]이라고 indexing을 하는 것은 다음과 같은 의미를 가집니다.

 

[1, 3]에서 가장 먼저 적힌 요소인 1은 가장 바깥쪽 array 기준으로 index = 1인 요소를 가르킵니다.

즉, 가장 바깥쪽 array에는 [1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]처럼 총 3개의 요소가 존재하며,

그 중에서 index = 1인 요소는 [6, 7, 8, 9, 10]이라는 내부 array이죠.

 

그리고 [1, 3]에서 두 번째 요소인 3은 index = 1에서 골라진 요소 속에 존재하는 index = 3인 값을 의미합니다.

가장 바깥쪽 array에서 index = 1인 요소는 [6, 7, 8, 9, 10] 이었습니다.

여기서 index = 3인 요소는 바로 9이겠지요.

따라서 최종적으로 9가 출력되는 것입니다.

 

 

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]

nda_test[:, 3]

 

이제 이걸봅시다.

이번엔 첫 번째 요소에서 숫자가 아닌 콜론(:)이 적혀있습니다.

콜론(:)은 모든 것을 의미합니다.

(Pandas DataFrame의 loc method에서 모든 행이나 모든 컬럼을 추출할 땐 loc[:, :] 등으로 쓰는 것과 동일한 맥락입니다.)

 

따라서 위 indexing의 의미는

: -> 가장 바깥쪽 array기준으로 모든 요소들에 대해서

3 -> index = 3인 요소를 모두 뽑으라는 것입니다.

 

[1, 2, 3, 4, 5] 에서 index = 3인 요소는 4입니다.

[6, 7, 8, 9, 10] 에서 index = 3인 요소는 9입니다.

[11, 12, 13, 14, 15] 에서 index = 3인 요소는 14입니다.

따라서 [4, 9, 14]가 출력됩니다.

 

 

 

 

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]

nda_test[1, :]

 

이제 위 예시가 뭘 의미하는지 대충 감이 오시나요?

 

콜론(:)이 모든 것을 의미한다는 것을 알고있는 채로 위 indexing을 바라보면 그 의미는 다음과 같습니다.

1 -> 가장 바깥쪽 array 기준으로 index = 1인 요소에 대해서

: -> 모든 값을 추출하라.

 

가장 바깥쪽 array 기준으로 index = 1인 요소는 [6, 7, 8, 9, 10]이라는 내부 array입니다.

그리고 이 값을 모두 추출하라고했으니 [6, 7, 8, 9, 10]이 추출되는 것이지요.

 

 

 

array의 indexing은 이렇습니다.

 

list_test = [
    [1, 2, 3, 4, 5],
    [6, 7, 8, 9, 10],
    [11, 12, 13, 14, 15]
]

print(list_test[1][3])

 

위 예시에서처럼 python의 list에서도 list속의 list 등과 같이 list 속에 여러 개의 내부 list(nested list)가 있으면 가장 바깥쪽부터 indexing을 합니다.

array도 그와 마찬가지라고 볼 수 있습니다.

다만 numpy array에선 indexing을 할 때 콤마를 사용한하지만 python list에서는 콤마가 아닌 여러 개의 대괄호[]를 사용한다는 차이가 있겠네요.

 

 

 

 

 

 

 

 

 

 

 

 

 

import numpy as np

arr_test = np.array([1, 2, 3, 4, 5], ndmin=2)
print(arr_test)



-- Result
[[1 2 3 4 5]]

array method의 ndmin option은 생성될 array의 최소 차원을 지정할 수 있습니다.

위 예시에서 [1, 2, 3, 4, 5]의 1차원 list가 array에 전달되었지만 return되는건 2차원입니다.

ndmin 옵션이 2로 설정되어있기 때문이죠.

 

 

 

 

 

 

 

array는 여러가지 연산을 적용할 수 있습니다.

 

다음 예시를 봅시다.

 

array와 어떤 상수간의 사칙연산에 관한 예시입니다.

import numpy as np

arr_1 = np.array([3, 6, 9])
# arr_2 = np.array([1, 2, 3])
print(arr_1)  # -> [3 6 9]

arr_result = arr_1 + 3
print(arr_result)  # -> [ 6  9 12]

arr_result = arr_1 - 3
print(arr_result)  # -> [0 3 6]

arr_result = arr_1 * 3
print(arr_result)  # -> [ 9 18 27]

arr_result = arr_1 / 3
print(arr_result)  # -> [1. 2. 3.]


-- Result
[3 6 9]
[ 6  9 12]
[0 3 6]
[ 9 18 27]
[1. 2. 3.]

array에 어떤 상수를 더하고/빼고/곱하고/나누면 array에 존재하는 모든 요소에 대해 이 상수를 더하고/빼고/곱하고/나눈 결과를 return합니다.

 

 

 

 

 

 

이번에는 array끼리의 연산에 대해 알아보죠.

import numpy as np

arr_1 = np.array([3, 6, 9])
arr_2 = np.array([1, 2, 3])
print(arr_1)  # -> [3 6 9]
print(arr_2)  # -> [1 2 3]

arr_result = arr_1 + arr_2
print(arr_result)  # -> [ 4  8 12]

arr_result = arr_1 - arr_2
print(arr_result)  # -> [2 4 6]

arr_result = arr_1 * arr_2
print(arr_result)  # -> [ 3 12 27]

arr_result = arr_1 / arr_2
print(arr_result)  # -> [3. 3. 3.]


-- Result
[3 6 9]
[1 2 3]
[ 4  8 12]
[2 4 6]
[ 3 12 27]
[3. 3. 3.]

보시면 array끼리 사칙연산을 적용했을 때 array에 있는 동일한 위치의 요소들끼리 사칙연산이 적용됩니다.

 

arr_1 * arr_2를 봐보면 계산 방식이 다음과 같습니다.

1. arr_1의 index=0위치에 있는 값과 arr_2의 index=0 위치에 있는 값이 곱해져서 새로운 array의 index=0위치에 return됩니다.

2. arr_1의 index=1위치에 있는 값과 arr_2의 index=1 위치에 있는 값이 곱해져서 새로운 array의 index=1위치에 return됩니다.

3. arr_1의 index=2위치에 있는 값과 arr_2의 index=2 위치에 있는 값이 곱해져서 새로운 array의 index=2위치에 return됩니다.

 

수학에서 배우는 (a + b) * (c * d) = ac + ad + bc + bd 처럼 array끼리 곱할 때 뭔가 array에 괄호도 있고 해서 이렇게 분배법칙으로 곱셈을 할 것 같은 느낌도 들지만 전혀 그렇지 않습니다.

 

 

 

 

 

 

이러한 특성 때문에 array간의 연산을 적용할 때에는 반드시 array의 크기(요소의 개수)와 모양(차원)이 반드시 동일해야합니다.

아래 두 예시처럼 사칙연산을 적용할 array들의 크기(요소의 개수)와 형태(차원)가 동일하지 않다면 Error가 발생합니다.

 

 

array의 차원이 동일하지만 크기가 다른 array끼리 사칙연산을 하는 경우 -> Error 발생

import numpy as np

arr_1 = np.array([3, 6, 9])
arr_2 = np.array([1, 2])
print(arr_1)
print(arr_2)

arr_result = arr_1 * arr_2
print(arr_result)


-- Result
ValueError: operands could not be broadcast together with shapes (3,) (2,)

 

array에 담긴 요소들의 총 개수가 동일하지만 차원이 다른 array끼리 사칙연산을 하는 경우 -> Error 발생

import numpy as np

arr_1 = np.array([[3, 6, 9], [2, 4, 8]])
arr_2 = np.array([1, 2, 3, 4, 5, 6])
print(arr_1)
print(arr_2)

arr_result = arr_1 * arr_2
print(arr_result)


-- Result
ValueError: operands could not be broadcast together with shapes (2,3) (6,)

 

 

 

 

 

 

728x90
반응형
Comments