넘파이의 sub-array 만들기

조회수 674회

안녕하세요. 넘파이를 이용하여 기존 배열의 subarray를 생성하는 함수를 만드려고 하고 있습니다. 예를 들면 밑의 코드처럼 기존의 배열과 만들고자하는 subarray의 shape, 기존배열에서 중심이되는 부분(center), fill 등의 파라미터를 입력받은 후,

import numpy as np

def sub_array(array, shape, center, fill=None):
    # ... your code here

밑의 사진처럼 만들고 싶습니다.

이미지이 사진에서 Sub-array-center (orange)는 기존 행렬기준 (2, 2), sub-array (red)의 shape은 (4, 3)입니다. 이미지 그런데 만약 subarray가 범위를 초과할 경우, 그리고 fill에 내용이 입력되는 경우에는 (이 예시에서는 1) 그 입력된 숫자로 초과된 범위를 채워넣고자 합니다.

그래서 코드를 아래와 같이 짜봤는데 fill이 없을 경우는 나름 실행이 되지만 fill이 들어 갈 경우에는 여기서 어떤 코드를 더 입력해 봐야 할지 아니면 코드를 처음부터 뒤엎는 게 좋을 지 모르겠습니다. 아직 코딩이 처음이라 코드가 지저분한 점 양해 부탁합니다!

def subarray(array, shape, center, fill=None):
    """Calculate sub_array of numpy array."""
    if shape[0] % 2 == 0:
        raw = ((shape[0] // 2) - 1, (shape[0] // 2))
    if shape[0] % 2 == 1:
        raw = ((shape[0] // 2), (shape[0] // 2))
    if shape[1] % 2 == 0:
        col = ((shape[1] // 2) - 1, (shape[1] // 2))
    if shape[1] % 2 == 1:
        col = ((shape[1] // 2), (shape[1] // 2))



    new_array = array[center[0] - raw[0]: (center[0] + raw[1] + 1), center[1] - col[0]: (center[1] + col[1] + 1)]
    #np.append(new_array, np.full(()))
    return new_array
  • (•́ ✖ •̀)
    알 수 없는 사용자

2 답변

  • 빈 공간을 채워줘야 하는 상황에서 fill에 아무런 값이 들어오지 않으면 어떻게 해야할지 고민을 해야 할 것 같지만, 일단은 그런 경우가 없다고 생각하겠습니다.

    저라면 이 문제를 해결하기 위해

    1. 중심이 되는 부분의 좌표와 크기정보를 이용해 배열의 새로 만들 배열의 (0, 0) 부분이 될 좌표를 어떻게 찾을 것인지
    2. 새로 만들 배열의 빈 공간을 어떻게 채울 것인지

    를 고민할 것 같습니다.

    1번을 해결하기 위한 코드가 위의 조건문에 해당하겠죠?

    작성하신 코드를 요약하자면, 길이가 짝수일 경우 그 길이를 반으로 나눈 후에 1을 빼고, 홀수일 경우 반으로 나눈 후 소수점 이하는 버린다 라고 할 수 있겠습니다.

    그런데 사실 잘 생각해보면 저렇게 조건문으로 나눌 필요 없이 길이에서 1을 뺀 후 반으로 나누고 소수점 이하는 버린다로 작성하면 조건문으로 분기하지 않아도 한번에 처리할 수 있습니다.

    예를 들어 길이가 5일 경우 기존에는 5 // 2 = 2, 6일 경우 6 // 2 - 1 = 2였다면,

    (5 - 1) // 2 = 2, (6 - 1) // 2 = 2가 되는 것을 확인할 수 있습니다.

    둘째로는 새로 만든 배열의 빈 공간을 채우는 방법을 생각하고 계신데요,

    반대로 값이 채워진 상태의 배열을 선언하고 이 배열의 일부 값들을 주어진 배열에서 가져오는 방식으로 작성하시면 될 것 같습니다.

    np.ones(shape, int) * fill 의 형태로 작성하시면 원하는 값으로 채워진 배열을 얻을 수 있습니다.

    나머지는 그냥 잘 잘라서 덮어씌우기만 하면 됩니다 ㅎㅎ

  • numpy는 안 써봐서 잘 모르지만, 공식 문서에서 그럴싸한 것들을 찾아 첨부해봤습니다.

    import numpy as np
    
    z = np.arange(1, 31).reshape(5, 6)
    """
    array([[ 1,  2,  3,  4,  5,  6],
           [ 7,  8,  9, 10, 11, 12],
           [13, 14, 15, 16, 17, 18],
           [19, 20, 21, 22, 23, 24],
           [25, 26, 27, 28, 29, 30]])
    """
    
    z[1:5, 1:4] #[row split, column split]
    """
    array([[ 8,  9, 10],
           [14, 15, 16],
           [20, 21, 22],
           [26, 27, 28]])
    """
    
    np.block([
           [ z[1:5, 2:6],     np.ones((4, 1)) ],
           [ np.ones((1, 4)), np.ones((1, 1)) ]])
    """
    array([[ 9., 10., 11., 12.,  1.],
           [15., 16., 17., 18.,  1.],
           [21., 22., 23., 24.,  1.],
           [27., 28., 29., 30.,  1.],
           [ 1.,  1.,  1.,  1.,  1.]])
    """
    
    

    설명은 귀찮으니 패스!

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)