IDL/배열 생성 및 처리

배열 내 특정 값들의 탐색

이상우_idl 2024. 6. 11. 15:08
728x90
반응형

어떤 배열이 주어졌을 때 그 안에서 특정한 값을 찾아내고 싶은 경우를 가정해봅시다. 실제로 이러한 경우는 드물지 않습니다. 그렇다면 특정한 값을 배열 내에서 찾아내고자 하는 경우에는 어떻게 처리를 해야 할까요? 사실 어떻게 보면 매우 간단한 문제일 수도 있습니다. 예를 한번 들어봅시다. 다음과 같이 1차원 배열이 주어진 상황을 가정해봅니다.

 

data = [14, 58, 47, 92, 25, 66]

 

이렇게 6개의 값들로 구성된 1차원 배열 data가 있습니다. 여기서 25라는 값을 탐색하고자 합니다. 어떤 방법으로 처리하는 것이 좋을까요? 아무래도 이런 경우에는 WHERE 함수를 떠올리는 것이 인지상정(?)일 것 같습니다. 그렇다면 아마도 다음과 같이 처리하면 될 것 같습니다.

 

ww = WHERE(data EQ 25, count, /NULL)
PRINT, count
PRINT, ww
PRINT, data[ww]

 

그 결과는 다음과 같습니다. 여기서 count는 탐색된 건수, ww는 탐색된 배열 인덱스, data[ww]는 탐색된 값이 됩니다.

 

           1
           4
      25

 

이와 같이 25라는 값을 찾아냈고 그 위치가 인덱스 4라는 것도 확인할 수 있습니다. 따라서 data 배열 내에서 5번째 값이 25라는 것을 확인한 것입니다. 그러면 이번에는 50이라는 값을 찾아보기로 합시다. 그러면 위의 과정에서 WHERE 함수의 탐색 대상만 50으로 변경하면 됩니다.

 

ww = WHERE(data EQ 50, count, /NULL)
PRINT, count
PRINT, ww
PRINT, data[ww]

 

그러면 결과는 어떻게 될까요? 그냥 봐도 50이라는 값은 배열 내에 존재하지 않기 때문에 결과는 충분히 예측이 가능할 것입니다. 실제 결과는 다음과 같습니다.

 

           0
!NULL
!NULL

 

이와 같이 탐색 건수 자체가 0이므로, 탐색된 인덱스 및 탐색된 값이 모두 !null이 됩니다. 당연한 결과입니다. 그런데 이런 경우가 있습니다. 대상 배열 내에 50이라는 값 자체는 존재하지 않는다 하더라도 50에 가장 근접한 값이 어디에 있는가를 찾고 싶은 경우입니다. 즉 배열 내에 존재하지 않지만 가장 근접한 값을 찾아내고자 하는 경우입니다. 이런 경우에 대한 처리 알고리즘은 여러가지를 생각해볼 수 있겠지만 제 생각에는 다음과 같은 방법도 괜찮지않을까 싶습니다.

 

diffs = ABS(data-50)
ww = WHERE(diffs EQ MIN(diffs), count)

PRINT, count
PRINT, data[ww]

 

이와 같이 data 배열 내 모든 값들에 대하여 50이란 값과의 차이의 절대치를 계산하여 diff라는 배열에 담고 이 diff 배열 내에서 최소값의 위치를 찾는 것입니다. 출력된 결과를 보면 다음과 같습니다.

 

           1

           2

      47

 

일단 해당 값의 갯수인 count의 값은 1이고 해당 값의 위치 인덱스는 2인 것으로 확인됩니다. 그리고 해당 값 자체는 data 배열을 ww로 인덱싱하면 되는데, 그 값이 47인 것을 알 수 있습니다. 그러면 이러한 결과를 도식적으로 나타내보는 것도 좋을 것 같습니다. 이를 위하여 다음과 같은 과정에 의하여 플롯 형태의 그림으로 표출해봅시다.

 

win = WINDOW(DIMENSIONS=[600, 500], /NO_TOOLBAR)
p = PLOT(data, SYMBOL='circle', /SYM_FILLED, $
  SYM_SIZE=1.5, COLOR='green', $
  FONT_SIZE=12, CLIP=0, /CURRENT)
po = PLOT(ww, data[ww], SYMBOL='circle', /SYM_FILLED, $
    SYM_SIZE=1.5, COLOR='red', LINESTYLE=6, /OVERPLOT)

 

 

그러면 위와 같이 data 배열 내의 값들 중 50에 가장 근접한 47이라는 값만 다른 색상으로 나타낸 표출 결과를 얻을 수 있습니다. 이제 이번에는 data를 다음과 같이 30개의 실수형 값들로 구성된 배열로 대체해봅시다.

 

data = FINDGEN(n)*1.5+20+RANDOMU(-1, n)*8-4

 

이러한 상태에서 나머지 과정은 위와 똑같이 실행해보면 그 결과는 다음과 같을 것입니다.

 

           1
          19
      49.7244

 

 

이와 같이 새로운 data 배열 내에서 50에 가장 근접한 값은 49.7244라는 것을 알 수 있고 그 위치도 위와 같이 도식적으로 확인할 수 있습니다. 그리고 이번에는 배열 값이 50에 가장 근접한 결과를 찾는 대신 50으로부터 5 이내로 근접한 값들을 찾아봅시다. 즉 배열 내 값들 중 특정한 값으로부터 일정한 차이 이하의 값들을 찾아내는 경우로서, 여기서는 50-5부터 50+5의 범위 내에 속한 값들을 탐색하게 됩니다. 이를 위해서는 앞서 WHERE 함수가 사용되었던 내용만 다음과 같이 변경해주면 될 것입니다.

 

ww = WHERE(diffs LE 5, count)

 

즉 이와 같이 diff의 값이 5 이하인 경우들을 찾으면 됩니다. 이 상태에서 나머지 과정들을 그대로 똑같이 실행하면 결과는 다음과 같을 것입니다.

 

           7
          16          18          19          20          21          22          24
      47.2750      47.4299      49.7244      53.8764      54.0672      52.3140      54.5936

 

 

이와 같이 조건을 만족하는 값들의 갯수는 7개이고 그 값들도 확인할 수 있습니다. 따라서 배열 내에서 내가 원하는 값들을 탐색하는데 있어서는 대략 이와 같은 방식으로 처리하면 무난할 것 같습니다. 이러한 처리 방식은 1차원 배열 뿐 아니라 2차원, 3차원 등의 다차원 배열에 대해서도 동일하게 적용할 수 있습니다. 2차원 배열에 대하여 비슷한 방식의 처리를 적용한 예제를 그림만 보면 다음과 같습니다.

 

다만 2차원 이미지를 위와 같이 표출하기 위해서는 약간의 팁이 필요합니다. 일단 위와 같은 표출 방법에 관해서는 관련 게시물의 내용을 참조하시면 됩니다. 그리고 이러한 표출 방법에 관해서는 조만간 별도로 다뤄보도록 하겠습니다.

반응형