본문 바로가기

programming/내가 만들고 싶어서 만든 것!

Python을 활용한 '여름 길이' 분석하기 - (한 해의 여름은 몇일일까?)

반응형

1. 개요

 

 바로 전 게시물에서는 Python을 활용해서 매년 평균 온도를 분석하였다. 이 프로젝트를 진행하면서 기온에 대한 궁금증이 생긴 후, 여름에 대한 궁금증이 시작되었다. 내가 내린 결론은(코드가 완벽하다면) '서울의 평균 기온은 점점 올라가고 있다.' 이고 이는 '서울의 여름은 길어지고 있을까?' 라는 질문으로 이어졌다. 온도가 증가했으니 여름은 당연히 길어지지! 라고 말할 수 있지만, 봄, 겨울 가을의 평균 기온이 증가해도 같은 결과가 나올 수 있다. 궁금증이 생겼고 나는 Python으로 그래프를 그릴 수 있으니, 바로 코드를 작성하기 시작했다.

 

2. 코드설계

 

 코드를 작성할 때 가장 중요한 것 중 하나는 명확한 조건이다. 나에게는 여름의 길이를 구분할 수 있는 기준이 필요했다. 구글링을 해보니, 우리나라의 기상청에서 사용되는 여름 시작의 기준이 있었다. 이는 다음과 같다.


기상학에서는 기온 변화에 따라 계절을 구분한다. 대한민국 기상청은 여름의 시작을 일평균 기온이 20 이상으로 올라간 다시 떨어지지 않는 첫날로 정의하며, 나흘 전부터 나흘 후까지 9 동안의 평균 기온이 이틀 연속 유지될 때를 기준으로 한다.

 

출처: https://ko.wikipedia.org/wiki/%EC%97%AC%EB%A6%84

 

여름 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 하계는 여기로 연결됩니다. 다른 뜻에 대해서는 하계 (동음이의) 문서를 참조하십시오. 여름날은 여기로 연결됩니다. 다른 뜻에 대해서는 여름날 (동음이의) 문

ko.wikipedia.org


 위의 말을 잘 설명해준 기사의 글을 인용하자면 다음과 같다.


오늘을 예로 들면, 앞선 나흘(7~10일)과 11일, 이후 나흘(12~15일) 등 9개 일의 일평균 기온을 각각 구한 뒤 이 9일 동안의 평균기온을 계산하는 방식이다.

 

이렇게 해서 나온 기온이 이틀 연속 20도를 넘으면 "여름이 시작됐다"고 하는 것이다. 가령 11일자 평균기온(7~15일)이 20도인데 12일자 평균기온(8~16일)이 21도로 계산됐다면 여름의 시작일은 12일이다.

 

출처: https://newsis.com/view/?id=NISX20190510_0000647204

 

낮기온 30도인데, 기상청 계절은 여전히 봄…왜일까?

【서울=뉴시스】조인우 기자 = 주말 서울 등 일부 지역 낮 기온이 29도까지 오르는 더운 날씨가 예상된다

www.newsis.com


 그렇다면 이제 확실한 여름 시작의 기준을 정할 수 있다. 문제는 '여름의 끝'이었다. 아무리 찾아봐도 여름의 끝에 대한 명확한 기준은 없었다. 그러다 생각난 방법은 바로 '가을의 시작'을 찾는 것이었다. '가을의 시작'은 '여름의 끝' 이라는 인과관계에는 오류가 없다고 생각했기 때문이다. 그래서 가을의 시작을 알아보기 시작하였고 다음과 같은 명제를 찾을 수 있었다.


기상학적으로 가을의 기준은 일평균 기온이 20도 이하로 내려가기 시작해 9일간 지속하는 첫 번째 날을 가을의 시작으로 본다.

 

출처: https://namu.wiki/w/%EA%B0%80%EC%9D%84

 

가을 - 나무위키

농부들이 풍성한 수확의 기쁨을 나누며 술과 춤 잔치를 벌인다사계 - 가을 1악장의 소네트 秋 / Autumn, Fall[1][2] 일반적으로 9~11월[3][4]에 해당하는 1년 4계절의 세번째 계절. 1년 하반기의 한창일 무

namu.wiki


 이제 나에게는 데이터를 분류할 수 있는 명확한 기준이 생겼다. 여름의 시작부터 가을의 시작까지의 날짜를 계산하여 그 사이에 있는 날들의 갯수를 세면 그것이 바로 한 해에 해당하는 여름의 길이이다. 따라서 다음과 같이 코드를 설계하였다.

 

import csv
import matplotlib.pyplot as plt
f = open('Seoul_Weather.csv','r',encoding = 'cp949')
data = csv.reader(f)
header = next(data)

result = {}
countSummer = 0
countFall = 0
checkDay = 2
isSummer = False

for row in data:
    buff = row[0].split('-')
    
    if buff[0] != '1953' and buff[0] != '1952' and buff[0] != '1951'and buff[0] != '1950':    
        
        tmp = float(row[2])
        
        if tmp != '' and countSummer != 9:
            if tmp > 20:
                countSummer += 1
            elif countSummer > 0:
                countSummer = 0
        
        if countFall == 9:
            result[buff[0]] = checkDay
            isSummer = False
            checkDay = 2
            countFall = 0
            countSummer = 0
        
        if countSummer == 9:
            isSummer = True
        
        if isSummer == True:
            checkDay += 1
        
        if tmp != '' and countFall != 9 and isSummer == True:
            if tmp < 21:
                countFall += 1
            elif countFall > 0:
                countFall = 0
            
        

x = list(result.keys())
y = list(result.values())

plt.plot(x, y,'r')
plt.show()

 

 위의 코드를 실행해보면 다음과 같은 결과가 나온다.



 그래프의 x축에 해당하는 명칭은 년도이지만, 그것을 알아볼 수 없을 정도로 축의 밀접도가 높기에 그래프의 크기를 늘릴 수 있는 방법을 찾아보았다. 다행이도 외국 사이트에서 방법을 찾을 수 있었고 다음과 같이 코드를 변경해보았다. 사실 한 줄을 추가한 것 뿐이다.

 

import csv
import matplotlib.pyplot as plt
f = open('Seoul_Weather.csv','r',encoding = 'cp949')
data = csv.reader(f)
header = next(data)

result = {}
countSummer = 0
countFall = 0
checkDay = 2
isSummer = False

for row in data:
    buff = row[0].split('-')
    
    if buff[0] != '1953' and buff[0] != '1952' and buff[0] != '1951'and buff[0] != '1950':    
        
        tmp = float(row[2])
        
        if tmp != '' and countSummer != 9:
            if tmp > 20:
                countSummer += 1
            elif countSummer > 0:
                countSummer = 0
        
        if countFall == 9:
            result[buff[0]] = checkDay
            isSummer = False
            checkDay = 2
            countFall = 0
            countSummer = 0
        
        if countSummer == 9:
            isSummer = True
        
        if isSummer == True:
            checkDay += 1
        
        if tmp != '' and countFall != 9 and isSummer == True:
            if tmp < 21:
                countFall += 1
            elif countFall > 0:
                countFall = 0
            
        

x = list(result.keys())
y = list(result.values())

plt.figure(figsize=(20, 10))
plt.plot(x, y,'r')
plt.show()


 x축의 명칭은 거의 그대로인 수준이지만, 그래도 그래프를 보기 조금 편해졌다. 문제는 "나의 코드가 확실한가?" 이었다. 내가 읽은 프로그래밍 서적 중 가장 기억나는 명언 중 하나가 바로 "당신이 고민하는 그 일은 분명히 누군가는 고민했을 일이다." 이다. 모르는 문제는 검색을 통해 해결하라는 뜻인데, 이 문장을 떠올리며 나의 코드를 확인하기 위해 정확한 정보를 찾아보았다. 다행이 다음과 같은 기사를 읽을 수 있었다.


여름이 일찍 시작되고 가을이 늦게 시작되기 때문에 1년에서 여름이 차지하는 날도 점차 길어진다. 2001~2010년 118일이었던 여름은 2011~2018년엔 126일로 늘었다고 기상청은 설명했다.

 

출처: https://newsis.com/view/?id=NISX20190510_0000647204

 

낮기온 30도인데, 기상청 계절은 여전히 봄…왜일까?

【서울=뉴시스】조인우 기자 = 주말 서울 등 일부 지역 낮 기온이 29도까지 오르는 더운 날씨가 예상된다

www.newsis.com


 우리나라에서 통계를 다루는데 있어서는 의심할 여지가 없는 실력자들이 일하시는 기관에서 나온 결과이니 충분히 믿을만하다고 생각하였고, 나의 코드를 기상청의 결과와 내가 출력한 결과의 평균을 비교하기로 결심했다. 년도별로의 데이터를 사전형으로 정리하였기 때문에, 코드가 어렵지는 않았다. 평균을 내는 코드는 다음과 같다.

 

import csv
import matplotlib.pyplot as plt
f = open('Seoul_Weather.csv','r',encoding = 'cp949')
data = csv.reader(f)
header = next(data)

result = {}
countSummer = 0
countFall = 0
checkDay = 2
isSummer = False

for row in data:
    buff = row[0].split('-')
    
    if buff[0] != '1953' and buff[0] != '1952' and buff[0] != '1951'and buff[0] != '1950':    
        
        tmp = float(row[2])
        
        if tmp != '' and countSummer != 9:
            if tmp > 20:
                countSummer += 1
            elif countSummer > 0:
                countSummer = 0
        
        if countFall == 9:
            result[buff[0]] = checkDay
            isSummer = False
            checkDay = 2
            countFall = 0
            countSummer = 0
        
        if countSummer == 9:
            isSummer = True
        
        if isSummer == True:
            checkDay += 1
        
        if tmp != '' and countFall != 9 and isSummer == True:
            if tmp < 21:
                countFall += 1
            elif countFall > 0:
                countFall = 0
            
sum1 = 0
sum2 = 0

for i in range(2001,2011):
    sum1 += result[str(i)]
    
for i in range(2011, 2019):
    sum2 += result[str(i)]

print(sum1 / 10)
print(sum2 / 8)

 

위 코드의 결과는 다음과 같았다.


121.3

126.0


 2011년도의 결과는 정확하게 맞지만, 아쉽게도 2000년도의 결과는 3일정도 차이가 난다. 나의 코드가 큰 차이로 틀렸다고는 생각이 들지 않았다..

 

 이렇게 그래프를 그리고 나니, 년도 별로 비교할 수 있는 그래프를 그려지고 싶어졌다. 이 글을 쓰는 시점에 말이다...... 결국 임시저장을 누르고 비교하는 코드를 작성해보았다.

 

 코드는 비교적 간단하였다. 년도를 key의 값으로 주고, 해당하는 여름의 길이를 value값에 넣어주면 된다. 다만 아쉬운 점은 한글을 사용하지 못해 모는 label을 영어로 했다는 점과 그래프가 조금은 복잡해 보인다는 점이다. 이는 해당 년도를 표시하고 그래프의 바탕을 좌표로 설정하는 등의 방법을 시도해보았다. 다음은 소스코드이다.

 

import csv
import matplotlib.pyplot as plt
f = open('Seoul_Weather.csv','r',encoding = 'cp949')
data = csv.reader(f)
header = next(data)

result = {}
countSummer = 0
countFall = 0
checkDay = 2
isSummer = False

for row in data:
    buff = row[0].split('-')
    
    if buff[0] != '1953' and buff[0] != '1952' and buff[0] != '1951'and buff[0] != '1950':    
        
        tmp = float(row[2])
        
        if tmp != '' and countSummer != 9:
            if tmp > 20:
                countSummer += 1
            elif countSummer > 0:
                countSummer = 0
        
        if countFall == 9:
            result[buff[0]] = checkDay
            isSummer = False
            checkDay = 2
            countFall = 0
            countSummer = 0
        
        if countSummer == 9:
            isSummer = True
        
        if isSummer == True:
            checkDay += 1
        
        if tmp != '' and countFall != 9 and isSummer == True:
            if tmp < 21:
                countFall += 1
            elif countFall > 0:
                countFall = 0

division = {}

for i in range(1910,2011,10):
    if i // 10 == 195:
        continue
    buff = []
    for j in range(i, i + 10):
        buff.append(result[str(j)])
    division[i] = buff

x = [i for i in range(0,10)]

plt.figure(figsize=(20, 10))

for key,value in division.items():
    plt.plot(x,value,label = str(key))
plt.legend(loc='upper right')
plt.xlabel('year')
plt.ylabel('Length of Summer')
plt.grid(True)
plt.show()

 

 위 코드의 결과는 다음과 같다.



 결과를 간단하게 정리하기 위해 두개의 그래프만을 비교해보겠다. 파란색은 1910년도에 해당하고 하늘색은 2010년도에 해당한다. 이렇게만 100년사이에 여름이 얼마나 늘어났는지 훨씬 쉽게 비교할 수 있을 것이다. 다음은 이 두개만을 남겨놓은 그래프이다.



 이렇게 확인하니 확실히 100년 동안 여름이 늘어났다는 명제는 참인 것 같다. 조금 신기한 부분은 그래프의 모양이 어느정도 일치한다는 것이다.

 

3. 결어

 

 "공부는 목표를 이룰 수 있는 하나의 도구다." 내가 정말 존경하는 사이트안 생활코딩 강의에서 들은 말이다. 나는 여름의 길이를 알고싶었고, 이를 년도마다 비교하고 싶었다. 우연하게 읽은 데이터 분석 책으로 옛기억을 떠올리며 하나하나 자료를 찾아가며 공부하였다. 누구도 시켜서 한 공부도 아니었지만, 오히려 더욱 집중이 잘 되었다. 앞으로 이런 종류의 글을 많이 올렸으면 좋겠다.

반응형