우리가 작업을 하다보면 값의 자료형(Data Type)을 변환해야 하는 경우들이 종종 있습니다. 오늘은 그 중에서도 문자를 숫자로 변환하는 경우를 보고자 합니다. 특히 겉으로 보기엔 숫자이긴 하지만 실제로는 문자형으로 존재하는 값을 숫자로 변환하는 경우입니다. 예를 들면 다음과 같습니다.
a = '37'
b = FIX(a)
HELP, b
PRINT, a
이와 같이 a는 '37'이라는 문자형 값인데 FIX 함수를 사용하여 정수형 값으로 변환하는 경우입니다. 이 과정을 IDL 커맨드 입력창에서 실행해보면 결과는 다음과 같습니다.
IDL> a = '37'
IDL> b = FIX(a)
IDL> HELP, b
B INT = 37
IDL> PRINT, b
37
이와 같이 37이라는 정수형 값으로 변환된 것을 알 수 있습니다. 그런데 이번에는 변수 a의 값을 '42861'이라는 문자형 값으로 대체하고 다시 실행해 봅시다.
IDL> a = '42861'
IDL> b = FIX(a)
IDL> HELP, b
B INT = -22675
IDL> PRINT, b
-22675
이 결과를 보면 뭔가 문제가 있음을 알 수 있습니다. 즉 원래 의도와는 달리 정수형으로 변환된 결과는 -22675로 전혀 엉뚱한 값이 되어 있습니다. 그 이유는 정수형은 유효 범위가 -32768~+32767이라서 42861이라는 값을 수용할 수 없기 때문입니다. 제대로 변환하려면 그냥 정수형 대신 긴 정수(Long Integer) 자료형으로 변환되도록 해야합니다. 이를 위해서는 FIX 대신 LONG 함수를 사용하면 됩니다. 이렇게 처리해보면 결과는 다음과 같습니다.
IDL> a = '42861'
IDL> b = LONG(a)
IDL> HELP, b
B LONG = 42861
IDL> PRINT, b
42861
이와 같이 정상적인 결과를 얻을 수 있습니다. 그리고 긴 정수형 외에도 실수형(Float)으로 변환해볼 수도 있습니다. 이를 위해서 FLOAT 함수를 사용해보면 결과는 다음과 같습니다.
IDL> a = '42861'
IDL> b = FLOAT(a)
IDL> HELP, b
B FLOAT = 42861.0
IDL> PRINT, b
42861.0
물론 이 경우에는 실수형으로의 변환이기 때문에 소수점이 붙게 되지만 값 자체는 제대로 변환되었다고 볼 수 있습니다. 이와 같이 숫자의 모습을 띈 문자형 값을 숫자 자료형으로 변환할 경우에는 정수, 긴 정수, 실수 중 어떤 자료형으로 변환하는 것이 적합할 것인가에 대하여 미리 주의를 기울여야 합니다. 우리가 텍스트 형태의 자료 파일을 읽을 경우에도 똑같은 주의가 필요합니다. 예를 들어서 다음과 같이 자료값들이 수록된 텍스트 파일을 읽는 경우를 생각해봅시다.
year,month,day,data1,data2
2022,09,12,22781,1024.40
2022,09,13,19772,1022.73
2022,09,14,36108,1025.51
2022,09,15,42965,1026.08
2022,09,16,28184,1025.42
이 파일은 제가 가상으로 만든 것이며 아래 링크를 통해서도 받으실 수 있습니다.
IDL에서 이러한 텍스트 파일을 읽는 방법들에 관해서는 제가 예전에 관련 게시물들("텍스트 파일을 효과적으로 읽는 방법에 관하여" 1~5)을 올린 적이 있기 때문에 그 과정에 대한 자세한 설명은 생략하겠습니다. 먼저 IDL 자체에 수록된 관련 기능들(OPENR, READF 등)을 사용하는 방법부터 보면 그 과정은 대략 다음과 같습니다.
file = 'test_data.txt'
ss = ''
OPENR, lun, file, /GET_LUN
READF, lun, ss
data = !null
FOR j = 0, 4 DO BEGIN
READF, lun, ss
spl = STRSPLIT(ss, ',', /EXTRACT)
data = [data, FIX(spl[3])]
ENDFOR
FREE_LUN, lun
HELP, data
PRINT, data
일단 대상이 되는 텍스트 파일 내에 수록된 내용을 보면 각 라인마다 값들이 코마(,)로 구분되어 있습니다. 따라서 각 라인을 읽고 구분자(,)로 나누면 5개의 문자값들로 구성된 spl이라는 배열을 얻게 되는데, 여기서 네번째 문자값을 추출하여 정수형으로 변환하고 이 값을 data라는 배열에 누적시키는 과정이라고 보면 됩니다. 이렇게 얻어진 최종 결과인 data에 대한 출력 결과를 보면 다음과 같습니다.
DATA INT = Array[5]
22781 19772 -29428 -22571 28184
이와 같이 5개의 정수형 값들로 구성되는데, 실제로 추출되어 수록된 값들을 보면 원래 파일에 있던 값들과는 다릅니다. 특히 세번째 및 네번째 값이 전혀 엉뚱한데, 그 이유는 앞서 설명했던대로 정수형으로는 감당할 수 없는 값이기 때문입니다. 따라서 정상적으로 결과를 얻으려면 다음과 같이 반복형 구문 내에서 FIX 대신 LONG 함수를 사용하면 됩니다.
data = [data, LONG(spl[3])]
이렇게 수정한 후 다시 실행해보면 결과는 다음과 같습니다.
DATA LONG = Array[5]
22781 19772 36108 42965 28184
이와 같이 정상적인 결과를 얻을 수 있습니다. 그리고 텍스트 파일을 읽는 방법에 있어서 READCOL 명령을 사용하는 경우도 있습니다. 그 방법도 제가 앞서 언급했던 관련 게시물들("텍스트 파일을 효과적으로 읽는 방법에 관하여" 1~5)을 통하여 소개해드린 바 있습니다. 그래서 과정으로 바로 들어가보면 대략 다음과 같습니다.
file = 'test_data.txt'
READCOL, file, data, FORMAT='X,X,X,I'
HELP, data
PRINT, data
여기서는 파일 내에서 네번째 컬럼에 수록된 값들만 추출하여 data라는 배열로 담게 되는데, 그 값들을 정수형으로 읽기 위하여 READCOL의 FORMAT 키워드 내에서 I로 명시하였습니다. 일단 이 과정을 실행한 결과는 다음과 같습니다.
DATA INT = Array[5]
22781 19772 -29428 -22571 28184
이미 충분히 예상되었던 비정상적인 결과입니다. 따라서 정상적인 결과를 얻기 위해서는 자료형을 정수 대신 긴 정수형으로 바꿔줘야 하는데, 이를 위해서는 FORMAT 키워드 내에서 I 대신 L을 사용하면 됩니다.
READCOL, file, data, FORMAT='X,X,X,L'
HELP, data
PRINT, data
이렇게 해주면 결과는 다음과 같습니다.
DATA LONG = Array[5]
22781 19772 36108 42965 28184
이와 같이 정상적인 결과를 얻을 수 있습니다. 물론 긴 정수형 대신 실수형으로 결과를 얻는 것도 가능합니다. 이를 위해서는 첫번째 방법에서는 FLOAT 함수를 사용하거나 두번째 방법에서는 FORMAT 키워드에서 F를 사용하면 됩니다.
data = [data, FLOAT(spl[3])]
READCOL, file, data, FORMAT='X,X,X,F'
결과는 다음과 같습니다.
DATA FLOAT = Array[5]
22781.0 19772.0 36108.0 42965.0 28184.0
이와 같이 문자형으로 존재하는 값들을 숫자 자료형으로 변환하는데 있어서 정확히 어떤 자료형으로 할 것인지에 대하여 사전에 충분한 고려가 필요합니다. 그렇게 하지 않을 경우에는 원래의 의도와 전혀 다른 엉뚱한 결과를 얻게 될 수도 있다는 것을 반드시 유의해야 합니다.
'IDL > Data Type & Format' 카테고리의 다른 글
ASDF 형식 파일의 생성 및 읽기 (0) | 2023.11.02 |
---|---|
SER 포맷의 파일 읽기 (0) | 2023.03.20 |
IDL의 폰트 체계 및 활용 [3] Device Font (2) | 2022.09.23 |
IDL의 폰트 체계 및 활용 [2] True Type Font (0) | 2022.09.20 |
IDL의 폰트 체계 및 활용 [1] Hershey Vector Font (0) | 2022.09.15 |