반응형

파이썬 보간법(python interpolation)

부제: 그래프 그림만 있을 때 추출한 값의 결측치를 찾아내기

 

그림만 있는 그래프에서 값을 추출하는 디지타이저 프로그램을 간략히 소개했었습니다.(그래프 그림만 있을 때 값 추출하기 : 디지타이저 Digitizer) 이게 단순한 프로그램이면서 참 편하기는 한데, 문제는 연속된 선에서 값을 한없이 연속되게 찍을 수 없다는 것입니다.

 

무슨 말이냐면, 아래 그림처럼 연속된 선을 가지는 그래프에서 점을 찍는다 하더라도 빈 값(결측값, missing value)가 생기기 마련입니다. 파란색 선에 파란색 +로 찍어서 그런지 참 보기에는 안 좋네요.

 

만약에 엄청난 노력을 쏟아부어 중간중간에 마우스 클릭을 열심히 한다고 해도 결측값은 생기기 마련입니다. 더군다나 디지타이저로 추출해낸 값은 아래 그림과 같이 x축의 값과 그 간격이 제멋대로 되어 있습니다.

 

 

뭐, 저렇게 추출된 값이라도 내가 연구한 결과랑 그래프로 같이 그려서 대강 비교하겠다면 상관없을 겁니다. 하지만 경우에 따라서는 특정 x값에서 y값이 무엇인지 알고 싶을때가 있습니다. 예를 들어 디지타이저로 추출한 x = 58.98 일때 y = 13.219이 아니라, x = 60일 때, y값이 필요할 수 있습니다.

 

이 경우에는 간단하게 보간법(interpolation)을 이용하여 결측값을 구하는게 가장 합리적인 방법일 겁니다. 실제로 저도 학위과정 중에 디지타이저로 추출한 값은 그대로 쓰지 않았고, 보간을 한번 거친 값을 썼습니다.

 

엑셀을 잘 다루시는 분들은 엑셀로도 한다고 하지만, 저는 파이썬으로 간단한 보간을 하였습니다. 위의 그래프를 추출한 값을 간단히 보간하는 방법은 아래 파이썬 예시 코드와 같습니다.

 

import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate

data = np.loadtxt("디지타이저_추출값.csv", delimiter=',', dtype = np.float32, skiprows=1)

x_ori = data[:,0]
y_ori = data[:,1]

f1 = interpolate.interp1d(x_ori,y_ori)
f2 = interpolate.interp1d(x_ori,y_ori, kind='cubic')

x_new = np.linspace(24,1055,num=1032,endpoint=True)

plt.plot(x_ori,y_ori,'o',x_new,f1(x_new),'-',x_new,f2(x_new),'--')
plt.legend(['data','linear','cubic','spline'], loc='best')

plt.show()

 

  • 일단 numpy와 scipy를 쓰는데, scipy로 보간을 하는 겁니다. matplotlib이야 그래프를 보이기 위함입니다.
  • loadtxt로 csv파일을 읽어오는데, 콤마(',')로 값이 구분되어 있으며, 실수값(float32)이며, 1번째 줄은 건너뛰고(skiprows=1) 데이터를 읽어옵니다.
  • interp1d 함수에서 kind 값은 어떠한 방법으로 보간을 할 것인지 정하는 것으로 'linear', 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'previous', 'next' 중 하나가 될 수 있습니다. 따로 명시를 하지 않으면 linear입니다.
  • f1, f2는 마치 함수와 같아서 f1(50)을 출력해보면 x=50인 위치의 y값을 보간하여 반환합니다. 단 보간 이전의 데이터 x의 최소값보다 작은 값이나, 최대값보다 큰 값을 넣게 되면 오류가 납니다.

 

위의 코드를 실행하면 다음 그림과 같습니다. 그림이 작아서 무슨 차이일까 싶지만, x값이 드문드문 있다면 그 차이가 확연하게 나타날 것입니다.

디지타이저 등으로 기껏 고생해서 값을 추출했는데, 결측값이 있다고 좌절하지 마시고 파이썬 등으로 간단히 결측값을 찾아내어 쓰시면 됩니다.

반응형

+ Recent posts