IDL/Programming

누적에 의한 배열 생성법

이상우_IDL 2012. 7. 8. 16:12
728x90

오늘은 누적에 의한 배열 생성법에 관하여 살펴볼까 합니다. 일단 스칼라 값의 예를 들면 우리가 다음과 같은 작업을 하는 경우가 있습니다.


data = [45, 81, 61, 92, 107]

sum = 0

FOR i = 0, N_ELEMENTS(data)-1 DO sum = sum + data[i]


즉, 5개의 값들로 이루어진 data라는 배열의 구성원소들의 총합을 구하기 위하여, 반복문을 사용하여 data 배열내의 값을 계속 누적해서 더하는 방식입니다. 이 때 sum이라는 변수의 초기값은 0으로 두고 여기에 배열원소값을 순차적으로 더하여 누적시키는 방식입니다. 물론 이러한 작업의 경우 TOTAL이라는 내장함수를 사용하면 바로 끝나긴 하지만, 반복에 의한 스칼라 값의 누적이라는 예를 들기 위하여 이렇게 해보았습니다.


그런데 이와 유사한 방법론을 사용하여 배열을 생성하고 싶은 경우가 있습니다. 예를 들어, 위의 예제에서 80보다 큰 값을 갖는 원소들만 추려내어 새로운 배열을 만든다고 합시다. 물론 WHERE 함수를 사용하면 금방 해결이 되지만, 만약 WHERE 함수의 논리식보다 더 복잡한 연산을 통하여 원하는 원소들을 추출해야 하는 경우도 있을 수 있습니다. 그러면 이와 같은 과정을 통하여 선택된 원소들의 갯수가 몇 개가 될지를 사전에 알기 힘든 경우도 있습니다. 그럴 경우 초기 배열을 다음과 같이 아예 Null과 같은 형태로 만들어놓고 여기에 배열원소를 계속 덧붙이는 방법을 사용할 수 있습니다.


data = [45, 81, 61, 92, 107]

selected = []

FOR i = 0, N_ELEMENTS(data)-1 DO BEGIN

  IF data[i] GT 80 THEN selected = [selected, data[i]]

ENDFOR

HELP, selected

PRINT, selected


HELP와 PRINT로 출력된 결과를 보면 우리가 원하던대로 작업이 이루어졌음을 확인할 수 있습니다. 여기서 selected라는 배열을 초기에 []로 선언해 놓았습니다. 즉 배열은 배열인데 구성원소가 하나도 없는 공(vacant)배열이란 의미입니다. 이와 같은 내용은 다음과 같이 !null이라는 시스템 변수를 사용해도 마찬가지입니다.

selected = !null

이러한 Null 자료의 개념은 8.0버전부터 도입되었습니다. 그 이전 버전에서는 배열이 가질 수 있는 최소한의 원소갯수인 하나의 원소를 갖는 배열로 만들어놓고 누적을 다 끝낸 다음 첫번째 원소를 제외한 나머지 원소들을 추출하는 방식으로 했었지만, 8.0버전부터는 굳이 이렇게 안하고 위와 같이 할 수 있게 되었습니다. 어쨌든 위와 같은 방식을 사용하면, 원하는 조건을 만족하는 구성원소들만 따로 추출하여 새로운 배열로 생성하는 것이 가능합니다. 특히 그 조건을 만족하는 경우의 갯수를 사전에 알 수 없을 경우에 유용합니다.

그리고 이와 같은 배열의 누적은 1차원이 아닌 2차원 배열의 경우도 가능합니다. 예를 들어, 다음과 같이 쌍들이 여러개 모아진 2차원 배열이 있다고 가정해봅시다.

data = [[10, 3], [4, 7], [2, 2], [8, 5], [6, 7]]
HELP, data

여기서 HELP의 결과를 보면 2x5의 구조를 갖는 2차원 배열임을 알 수 있습니다. 즉, 5개의 쌍들로 이루어진 셈입니다. 그러면 이 쌍들중에서 서로간의 값의 차이가 2를 넘는 것들만 뽑아내는 경우를 생각해봅시다. 물론 그냥 눈으로 보면 정답은 보입니다. [10, 3], [4, 7], [8, 5]가 이 조건을 만족하는 쌍들이 되겠죠. 이걸 프로그래밍적으로는 어떻게 하느냐입니다. 역시 앞서 봤던 배열 누적의 방법을 사용할 수 있습니다. 프로그램의 내용은 아래와 같습니다.

sz = SIZE(data, /DIM)
selected = []
FOR i = 0, sz[1]-1 DO BEGIN
  diff = ABS(data[0, i]-data[1, i])
  IF diff GT 2 THEN selected = [[selected], [data[*, i]]]
ENDFOR
HELP, selected
PRINT, selected

여기서는 먼저 SIZE 함수를 사용하여 data 배열의 두번째 차원값을 추출하고 이 값을 반복인자로 사용하였습니다. 그리고 반복문안에서는 쌍으로 이루어진 두 값 사이의 차이의 절대치를 diff라는 변수에 담고 이 값이 2를 넘느냐 아니냐를 체크합니다. 이 때 IF문에서 selected를 누적시키는 방식을 주목해야 합니다. 꺾쇠괄호가 어떤 방식으로 사용되느냐가 관건인데, 앞서 1차원 배열의 경우와 비교해보면 내부적으로 []가 한 단계 더 추가되어 사용되었음을 알 수 있습니다.

어쨌든 이와 같은 작업을 실행한 결과를 확인해보면 우리가 앞서 예측했던 결과와 일치하는 것을 확인할 수 있습니다. 유사한 방식을 사용하면 아마 더 큰 차원의 배열에 대해서도 누적이 가능하겠지요. 제가 온라인이나 오프라인에서 항상 강조하지만 IDL에서는 배열을 얼마나 잘 다룰 수 있느냐가 프로그램의 효율을 높이는데 있어서 매우 중요합니다. 따라서 배열과 관련된 내장함수들을 잘 알아두는 것이 중요하지만, 지금 설명드린 것과 같은 내용은 IDL 도움말에서도 찾기가 쉽지 않은 내용인 것 같습니다. 도움이 되었으면 합니다.

LIST