본문 바로가기
파이썬으로 배우는 지구과학

파이썬을 이용하여 해수의 깊이에 따른 수온 변화 그래프 그리기

by 0대갈장군0 2022. 2. 17.
반응형

** 함께보면 좋습니다

 

해수의 연직방향(깊이에 따른) 수온변화

** 함께 보시면 좋습니다. 파이썬을 이용하여 해수의 깊이에 따른 수온 변화 그래프 그리기 중학교 과학이나 고등학교 지구과학 1 의 해양단원에서 학생들이 수도 없이 많이 보는 그래프가 있습

kalchi09.tistory.com

 

 

파이썬을 이용하여 동해바다의 계절별 연직 수온분포 그래프 그리기

지난 포스팅에서 동해바다의 연직방향 수온 분포 그래프를 그렸습니다. 해당 데이터는 4월 16일 데이터로, 봄에 해당하는 데이터인데, 이번에는 봄, 여름, 가을, 겨울 데이터를 모두 사용하여 그

kalchi09.tistory.com

중학교 과학이나 고등학교 지구과학 1 의 해양단원에서 학생들이 수도 없이 많이 보는 그래프가 있습니다.

 

깊이에 따른 수온변화 그래프인데, 교과서에는 아래와 같은 그림으로 소개됩니다.

데이터만 있으면 엑셀을 이용해도, 파이썬을 이용해도 어렵지 않게 그릴 수 있습니다. 다만 파이썬을 이용하면 y축이 역전되야 하고, x축은 아래가 아닌 위에 그려져야 하는 등 다소 코드가 길어지긴 하지만 본 포스팅은 파이썬을 활용한 그래프 그리기이기 때문에 적극적으로 파이썬을 이용해 보고자 합니다.

 

  1. 필요한 데이터 다운로드

그래프를 그리기 위해서는 해수의 깊이에 대한 수온 자료가 필요합니다. 이는 국립기상과학원 ARGO에서 다운로드 할 수 있습니다. 구글에서 국립기상과학원 ARGO라고 검색해도 되고, 아래 링크를 타고 들어가도 되는데, ARGO가 무엇인지는 지난 포스팅을 참고하면 됩니다.

 

▦ 국립기상과학원 ARGO

국립기상과학원 ARGO 사업 현황 2007년 11월 전 세계 해양에 3,000대 관측망 유지를 달성 하였으나, 이후 심해(4,000~6,000m) 및 생지화학적 요소 관측이 요구됨에 따라 새로운 목표인 4,200여대의 관측망

argo.nims.go.kr

(ARGO 링크 걸기)

국립기상 과학원 ARGO 홈페이지에 접속하면 상단에 ARGO NIMS라는것이 있는데 이걸 클릭하면 아래와 같은 화면이 나옵니다.

노란색이나 초록색, 보라색 좌표 표시는 현재 ARGO의 위치이고, 스크롤을 조금 내리면 ARGO에 따라 데이터를 최초로 습득한 날짜와 최근 습득한 날짜가 나옵니다. WMO_ID가 개별 ARGO에 부여되는 번호인데, 숫자의 왼쪽에 있는 체크박스에 체크를 하면 해당 ARGO가 그동안 움직인 궤적이 위의 지도에 보입니다. 원하는 것에 해당하는 WMO ID(초록색 숫자)를 클릭합니다. 본, 포스팅에서는 WMO_ID가 2901784인 ARGO가 습득한 데이터를 이용하였습니다.

그럼 아래와 같은 화면이 나옵니다. 맨 왼쪽은 자료 습득 날짜, 그 다음은 해당 자료에 부여되는 숫자, 이후 순서대로 자료를 습득한 위도와 경도, 깊이에 따른 수온-염분 변화 그래프, 수온-염분도(T-S diagram), 자료 구분이 있습니다. 회색 박스를 하나씩 클릭해보면 알겠지만, 궂이 그래프를 따로 그리지 않아도 수온+염분이라고 써 있는 회색 네모만 클릭해도 바로 깊이에 따른 해수 수온, 염분변화가 뜨기는 합니다. 그런데 염분도 함께 나와 이걸 빼고 그래프를 새로 그리고 싶다면, 자료 구분의 맨 오른쪽에 있는 회색 상자를 클릭해 봅시다. 그럼 자료가 txt 파일 형식으로 저장됩니다. 자료 구분의 맨 왼쪽은 파일 형식이 nc인 자료가 저장되는데, 이것도 파이썬으로 돌릴 수 있지만 별도의 라이브러리를 깔아야 합니다. 이건 해양이나 기상학 연구원 분들이 주로 사용하시는 형식입니다. 가운데 회색은 그냥 데이터를 새로운 창에서 띄워주는 탭입니다.

파일을 다운로드 하면, 텍스트 파일을 csv로 바꾸어야 하는데, 이 작업은 파이썬 보다 차라리 엑셀에서 하는게 속 편합니다. 파일이 엄청 많으면야 파이썬으로 돌려야 하겠지만 달랑 하나이니 그냥 엑셀에서 해 봅시다.

위 그림처럼, 우클릭 후 연결 프로그램으로 엑셀을 선택하여 텍스트 파일을 메모장에서 열지 말고 엑셀에서 열어 봅시다.

엑셀로 열어보면 알겠지만 맨 상단에 파이썬으로 그냥 돌리면 백 퍼센트 오류가 뜰 정보가 있습니다. 해당 열을 통째로 삭제해 줍시다.

여기서 주의할 것은, 데이터를 가만히 보면 # P T S와 이하 숫자가 모두 하나의 셀에 저장되어있습니다. 이러면 파이썬으로 데이터를 처리하기 불편해 집니다. 그러니 이걸 모두 3개의 셀로 쪼개주면 굉장히 편합니다. 방법은 간단합니다. 우선 데이터가 있는 셀 전체를 선택(ctrl + A)합니다. 그리고 메뉴에서 데이터 탭을 선택, 텍스트 나누기를 클릭 하면 구분기호로 분리, 너비가 일정함이라는 탭이 있다. 이 경우 너비가 일정하니 너비가 일정함을 선택 후 쭉 쭉 다음을 누루고 마침을 하면 됩니다. 구분기호로 분리를 선택한 후 공백으로 선택하고 작업을 해도 괜찮습니다. 어쨌든, 이 작업을 완료하면,

위와 같이 3개의 자료로 쪼개집니다. 여기서 #이 있는 탭은 마찬가지로 필요 없으니까 해당 셀을 통째로 지워 버립시다.

그리고 마지막으로 다른 이름으로 저장을 하고 파일 형식을 CSV(쉼표로 분리)로 지정한 뒤 원하는 파일 이름으로 쓴 뒤 저장하면 됩니다.

 

이제 파이썬으로 그래프를 그릴 준비는 모두 되었습니다. 여기까지의 과정이 복잡하고 길어 보이지만 사진을 다 붙이다 보니 그런 것이지 실제로 해 보면 5분도 채 걸리지 않습니다.

반응형

  2. 라이브러리 호출과 필요한 파일 읽기

(맨 마지막에 전체 코드를 텍스트로 적어 두겠으니 필요하신 분들은 그대로 드래그 하여 사용하세요.)

우선 그래프를 그리고, csv 파일을 다루어야 하니까 matplotlib.pyplot와 pandas 라이브러리를 호출하겠습니다.

다음으로, 파이썬에서는 기본적으로 그래프에 한글을 쓸 수 없습니다. 그래서 한글이 오류 없이 들어갈 수 있도록 아래 코드를 추가합시다. 그리고 만들어 놓은 csv파일을 읽어와야 하니, 아래 명령어를 사용하여 csv 파일을 읽어 옵시다.

한글 패치는 아래 코드를 복붙하시면 됩니다.

 

from matplotlib import font_manager, rc ##한글
rc('font', family='HCR Dotum')  ## 한글

 

아까 엑셀 파일에서 헤더 데이터를 보면 P, T, S 3가지로 데이터가 구성되어 있음을 알 수 있습니다. 여기서 P는 압력으로 깊이 대신 사용한 값입니다. 깊이 대신 압력을 사용해도 무방합니다. 깊어질 수록 압력이 증가하기 때문에. T는 수온이고, S는 염분입니다. 따라서 아래와 같이 명령어를 지정해 줍시다.

 

  3. for 문을 사용하여 압력을 깊이로 바꾸기

그런데 ARGO가 관측한 데이터는 y축이 깊이가 아닌 압력으로 주어졌습니다. 그대로 압력으로 써도 아무런 상관없지만, 전문가가 아니라면 압력이 그렇게 익숙하지는 않습니다. 정역학 평형 방정식을 이용하면 압력으로 바꾸는 것이 전혀 어렵지 않습니다. 관측 데이터에서 dbar라는 단위로 관측하였고, 1dbar=10,000Pa=10,000N/m^2 이니까, 정역학적 평형 방정식을 가지고 모든 압력 값을 깊이 값으로 바꾸어 줍시다. 이 때 해수의 밀도 단위가 필요한데, 해수 밀도 값은 1.027g/cm^3를 사용하였습니다. 여기까지의 코드는

여기서 depth라는 빈 리스트 자료를 먼저 만들었고, 그 다음에 for문을 이용하여, P에 있는 압력 값을 하나씩 순차적으로 깊이로 바꾼 뒤 depth라는 빈 리스트에 추가하라는 코드를 더 넣었습니다. 이 과정을 통해 모든 압력 값이 깊이 값으로 바뀌었습니다.

 

  4. plt. plot()를 사용한 기본 그래프 그리기

이제 아주 간단하게 그래프를 그릴 때 사용하는 코드를 입력해 주면 끝! 입니다.

그런데 만들어진 그래프를 보니 뭔가 해수의 깊이에 따른 수온 그래프와는 많이 다르고 어색합니다. 문제가 뭔지 보면

1. y 축 값(깊이)이 뒤집어져야 하고, 반전되어야 한다. 그러니까 위에서 아래로 숫자가 증가해야한다.

2. x 축의 값(수온)이 아래에 표시되지 않고 위에 표시되어야 한다.

3. 그래프가 길쭉하지 않다.

 

  5. 그래프의 크기 변경하기

하나씩 해결해 봅시다. 우선 그래프의 크기를 바꾸는 것 부터. 그래프의 크기를 바꾸는 것은 잘 알려진 코드이죠

plt.figure(figsize=(5,7))

저의 경우 5,7로 하였지만, 이는 개인에 따라 보기 좋은 형식으로 바꾸시면 됩니다. 저 위의 코드를 plt.plot(x,y)라는 코드 전에 넣어 주면 간단히 해결 됩니다.

 

 

  6. y축 역전(반전)

다음은 y축을 뒤집는 방법(반전시키는 방법)입니다. y축을 뒤집는 방법은 크게 두 가지가 있습니다.

 

1) plt.ylim은 y축의 최소값과 최대값을 지정해 주는 코드인데, 일반적으로 plt.ylim(10,100)처럼 최소값, 최대값 순서대로 적는다. 이걸 뒤집어서 최대값을 먼저 써 주면, 자연스럽게 뒤집어진다. plt.ylim(100,10)

 

2) 아래 코드를 이용해 뒤집습니다. 축과 관련된 왠만한 옵션은 대부분 plt.gca()에 있습니다. 여기에 축을 반전시키는 옵션도 있는데, 아래 코드처럼 쳐 줍니다.

plt.gca().invert_yaxis()

 

둘 중에 하나만 쳐 주면 되지만, 여기는 예제이기 때문에 전 아무 의미없이 두개 다 쳐 주겠습니다. 특히, x축과 y축의 범위도 지정해 주면 좋으니 그리 하였습니다. 그래서, 미리 x축의 범위와 y축의 범위를 모두 지정해 주었습니다. x축과 y축의 숫자 범위를 지정하는 방법을 많이 알려져 있죠.

plt.xlim(0,14)

plt.ylim(810,0)

이렇게 해서 코드를 실행하면,

  7. x축의 틱과 축 제목의 위치 바꾸기

많이 비슷해 졌는데, 아직 뭔가 어색합니다. x축의 틱(보조선)과 숫자, x축 이름이 모두 아래에 있어서 그렇습니다. 이녀석을 위로 올려줍시다. 아까전의 글에 축과 관련된 웬만한 옵션은 plt.gca()에 있다 하였는데, 이 아이도 여기에 있습니다.

plt.gca().xaxis.set_ticks_position('top')
plt.gca().xaxis.set_label_position('top')

이 두아이를 코드 중간에 넣어주면, 틱과 숫자, x축 제목이 모두 위로 올라갑니다. 위 코드에서 첫 번째는 틱과 숫자의 위치를, 두 번째는 축 제목의 위치를 지정해주는 코드라 생각하시면 됩니다. 이제 코드를 실행하면,

  8. 틱을 그래프 안으로 집어 넣기

이제 부터는 개인의 기호에 따라 그래프를 꾸미기만 하면 됩니다. 저는 개인적으로 x축과 y축의 보조선(틱)이 그래프 밖으로 나오는게 마음에 안들어 보조선(틱)이 그래프 안으로 들어가도록 하였습니다. 그 때 필요한 코드는

 

plt.tick_params(axis='x', direction='in')
plt.tick_params(axis='y', direction='in')

 

그리고 그래프의 제목을 달아주었습니다. 그래프의 제목을 다는 코드는 plt.title('그래프 제목')인건 너무 잘 알려져 있습니다. 또, 그래프에 그리드(보조선)가 있으면 보기 더 좋을 것 같아 보조선을 추가하였습니다.

 

  9. 그래프에 그리드(보조선) 그리기와 그래프 저장

plt.grid(linestyle='-.')

 

마지막으로 plt.savefig('저장할 경로명') 를 이용해 그래프를 저장하면 끝!

전체 코드를 보면 알 수 있겠지만, 코드가 전혀 어렵지 않습니다. 그래프를 이쁘게 그리기 위한 옵션일 뿐이지, 하나도 어렵지 않습니다. 어쨌든 저장된 최종 결과물은 짠~!

이제 좀 봐줄만한 그래프가 나왔습니다. 

 

  10. 그래프 해석하고, 혼합층 수온약층 심해층 찾아 이름 달기

해수의 연직 수온구조를 보면, 표층 부터 일정 깊이 까지 수온이 크게 변화하지 않는 층이 있습니다. 여기가 혼합층이죠. 그리고 깊이에 따라 수온이 급격히 변화하기 시작하는 층은 수온약층이고, 마지막으로 깊이에 따라 수온이 거의 변하지 않고 매우 낮은 수온을 보이는 층이 심해층입니다. 위 그래프에는 이 3개 층이 아주 전형적으로 잘 나타나고 있습니다. 해당 층에 맞도록 그래프에 이름을 적어보겠습니다. 

 

그래프에 글을 쓰는 명령어는 

 

plt.text(글자 x축 좌표, 글자 y축 좌표, '글자내용')

 

위 내용을 적용하여 글자를 달아보면

 

plt.text(11,30,'혼합층')
plt.text(8,120,'수온약층')
plt.text(1.5,400,'심해층')

 

글자까지 단 최종 결과물입니다. 

 

전체 코드를 아래에 적어두니 필요하신 분은

긁어다 쓰시고, 본 예제에 사용한 csv 파일도 함께 올려두겠으니 필요하신 분은 다운받아 쓰세요

 

##한글버전+압력을 깊이로
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib import font_manager, rc ##한글
rc('font', family='HCR Dotum')  ## 한글
data=pd.read_csv('C:\\111\\ARGO\\20200416\\20200416.csv')## 파일 경로
x=data['T']
y=data['P']
depth=[]
for press in y:
    z=press*10**4/1.027*1000/1000000/9.8
    depth.append(z)
print(depth)
plt.figure(figsize=(5,7)) # 그래프 크기 지정
plt.plot(x,depth)
plt.gca().invert_yaxis()
plt.gca().xaxis.set_ticks_position('top') ## x축 틱과 틱값 상단으로
plt.gca().xaxis.set_label_position('top') ## x축 제목 상단으로
plt.tick_params(axis='x', direction='in') ## x축 틱 안으로
plt.tick_params(axis='y', direction='in') ## y축 틱 안으로
plt.xlim(0,14)
plt.ylim(810,0)
plt.grid(linestyle='-.')  ## 그래프에 보조선
plt.xlabel('수온(℃)') ## x축 제목 지정
plt.ylabel('깊이(m)') ## y축 제목 지정
plt.text(11,30,'혼합층')
plt.text(8,120,'수온약층')
plt.text(1.5,400,'심해층')
plt.title('동해 수심에 따른 수온 변화 그래프\n날짜:2020/04/16   위도 : 37.1N   경도 : 132.223E') ## 그래프 제목
plt.savefig('C:\\111\\ARGO\\20200416_final.png',dpi=300)
plt.show()

** 참고

ARGO WMO ID : 2901784, 날짜 : 2020/04/16

2901784_092.csv
0.00MB

반응형

댓글