/ FUNDEMENTAL

미세먼지와 공시지가의 상관관계

#python #pandas #statistics

목차

미세먼지와 공시지가의 상관관계

abstract

  • 작년까지 말썽을 부린 미세먼지 문제와 현재진행형으로 사회적 이슈가 되고있는 집값문제. 두가지 요소가 서로 어떤 연관성을 가지고 있는지 데이터를 이용하여 분석한다. 서울의 s-dot프로그램의 일환으로 서울전역에 설치된 850개의 미세먼지 센서를 통해 수집된 데이터와 공시지가데이터를 전처리하여 시각화해보고 미세먼지가 많은 지역과 그렇지 않은 지역의 공시지가는 어떤 경향을 보이는지 알아본다. 통계적으로 두 변수가 연관이 있는지 알아보는 것으로 프로젝트를 마무리한다.

올해 초부터 Covid-19 바이러스가 세계적으로 대 유행을하면서 많은 분들이 아직까지도 힘든시기를 보내고 있죠. 여기까지 읽으셨다면 오늘은 제가 무슨 이야기를 할지 감을 잡으셨을 것 같은데…. 얘가 오늘은 코로나 관련해서 뭘 하려나보다 싶으셨을거에요. 틀렸습니다. 저는 코로나 이야기가 아닌 코로나로 인해 세상이 멈추다시피 헀지만, 반면 그로 인해 좋아진 점은 없을까 생각해봤어요.

코로나가 본격적으로 유행한 것은 올해 초부터이고 작년까지 우리의 ‘건강’에 대한 민감한 이슈는 뭐였나요? 불과 작년까지만 해도 우리의 건강에 관련된 최대 이슈는 미세먼지가 아니었나 싶어요.
매일 밖을 나설때마다 마스크를 쓰고 나가지만 사실 우리가 마스크와 친해졌던 건 보다 먼저 미세먼지가 기승을 부렸기 때문이었죠.

오늘은 하나의 주제가 아니라 한개를 더 이야기해볼꺼에요. 이것도 바로 한두달 전까지만해도 매일같이 뉴스에 나오던 이슈에요. 그건 바로…………………. 집값 문제였죠. 아마 관심이 없는 사람도 매일같이 뉴스에서 집값이 올랐다는 말로 도배를 해대니 한두번쯤은 들어봤을거에요.

각설하고 저는 미세먼지가 우리의 중요한 화두로 떠오를 무렵 문득 이런생각이 들었어요. 살기좋은 동네(집값이 비싼지역)은 미세먼지도 별로 없을까? 사실 살기 좋다는 것은 기준이 여러가지가 있을 수 있어서 맞을 것 같기도, 틀릴 것 같기도 하단 말이죠. 살기 좋다는 건 무엇보다 여러 인프라가 편리하다는건데 그러면 차량이나 사람이 붐비게 될 것 같으니 미세먼지도 많아질 것 같고, 집값이 비싸다는건 녹지가 주변에 잘 조성되어있다는 의미일수도 있으니까 미세먼지가 별로 없을수도 있다는 생각도 들고요. 반대로 미세먼지가 많아서 집값에 영향을 줄 수도 있겠죠. 그래서 오늘의 주제는 이거에요.

미세먼지의 농도와 공시지가의 상관관계를 알아보자!

왼쪽 그림은 2019년에 미세먼지 문제가 전년도에 비해서 많이 심각해졌다는 것을 알 수있고 오른쪽 그림은 최근 3년동안 집값의 변동을 알 수 있는 자료입니다. 따로 보면 알겠는데 이 둘은 어떤 상관관계를 가지고 있을까요? 이제 차근차근 저랑 알아가봅시다.

먼저 데이터 분석을 하려면 데이터가 있어야겠죠. 미세먼지 측정데이터는 서울시에서 디지털 행정기반 마련을 위해 실시하고 있는 스마트 도시데이터센서(S-dot) 측정값을 배포한 데이터셋을 사용했습니다. 오른쪽 그림은 센서위치 좌표를 이용해서 제가 시각화를 해본 그림입니다. 코드가 궁금하시면 세부정보를 눌러보세요.

```py geo = '/content/drive/My Drive/Data Science/강의노트/20201005-1009_LS_DS_project week1/Seoul1.geojson' # 서울시 중심부의 위도, 경도 center = [37.541, 126.986] # center를 중심으로 하고 zoom 단계에 해당하는 맵 생성 map2 = folium.Map(location = center, tiles = 'cartodbdark_matter', detect_retina=True, zoom_start=11) # 1000 개의 데이터만 그려냅니다. for i in location.index[:1000]: folium.Circle( location = location.loc[i, ['위도', '경도']], tooltip = location.loc[i, 'NO'], radius = 200 ).add_to(map2) map2.save('map2.html') map2 ```

데이터셋의 기간은 센싱 데이터는 2020년 4월, 공시지가는 2020년 공시지가 데이터셋을 가져왔습니다. 올해 초 코로나가 가장 심했을 때 중국도 셧다운이 됐었으니 중국으로 인한 영향이 적을 것 같아 4월의 데이터로 선정했습니다. 먼저 제가 계획한 분석을 하기 위해 필요한 데이터를 정리해봤습니다.

  • 서울시 미세먼지 센서 데이터 (시리얼번호, 미세먼지, 온도, 습도, 조도, 소음, 진동, 자외선, 풍속, 풍향 등)
  • 서울시 미세먼지 센서 위치정보(시리얼번호, 주소, 좌표값, 설치장소설명)
  • 서울시 공시지가(시군구명, 법정동명, 토지코드, 공시지가, 필지구분코드, 번지수 등)
  • 법정동_행정동 코드 데이터
  • 서울시 행정동을 경계로 한 지도데이터(jeojson)

공시지가와 미세먼지데이터를 직접적으로 비교하려면 센서가 위치한 장소와 측정값 이 두가지를 알아야 하겠죠. 측정값 자체는 누구나 볼 수 있게 공개되어 있는데 위치정보는 신청서를 작성하여 담당 공무원에게 보내서 자료를 직접 받아야 합니다. 따라서 위치정보와 측정값이 분리되어있는 자료인 것이죠. 그러면 분리된 이 두 자료를 합쳐야 할텐데 이때 1,2번 데이터에 공통으로 들어가있는 값이 뭐가 있을까요? 네 바로 센서 시리얼번호입니다. 이런식으로 각 자료를 합칠 때마다 공통된 열을 기준으로 값을 매핑시킬지 = merge 아니면 그냥 따로 자료를 이어붙일지 = concat 결정해야 하고 merge 한다면 각 자료의 교집합만 남길것인지 (how = inner) 합집합으로 합칠것인지(how = outer) 잘 고민해야 합니다.

추가적인 저의 데이터 전처리과정이 궁금하시다면 세부정보를 눌러주세요.

저는 센서의 값을 표만으로는 살펴보기가 힘들기 때문에 지도에 미세먼지 농도의 현황을 표현하고 싶었습니다. 그렇기 때문에 센서데이터를 지도에 표시하기 위해 각 센서의 주소를 시리얼번호를 기반으로 위치정보를 매핑시켜주었고 위치정보에 포함되어있는 주소를 세분화하여 법정동단위를 확보한 후, 공시지가 데이터셋과 법정동명을 기준으로 다시 매핑시켜주었습니다. 여기까지 센서데이터와 공시지가 데이터가 합쳐졌고 이제 이 데이터셋을 지도에 표현하기 위해 지도데이터(geojson)와 합쳐주어야 합니다. 제가 지도 시각화에 사용한 파이썬 라이브러리는 folium인데 이 패키지를 사용하려면 지도데이터와 지도에 표현할 데이터셋을 이어주는 매개체가 필요했고 저는 이 매개체를 행정동코드로 사용했습니다. 기존 센서,공시지가 데이터셋의 시군구코드와 법정동 코드를 합치면 행정동코드로 변환할 수 있다는 것을 구글링을 통해 알아낸 후, **법정동_행정동 코드데이터**를 법정동코드를 기준으로 행정동코드를 매핑시켜주었습니다.

전처리를 완료하고 미세먼지 농도와 공시지가의 관계를 알아보기 위해 간단하게 산점도를 그려 어떤 연관성이 있을지를 예상해봤습니다.

하지만 산점도로는 유의미한 연관성을 찾기 힘들었고 미세먼지와 공시지가의 상관계수(correlation)을 구해보았습니다.

상관계수 코드

```py Correlation = final[['미세먼지(㎍/㎥)','공시지가(원/㎡)']] Correlation.corr() ```

결과는…..전혀 상관이 없었죠. 믿을수가 없어서 지도에 나타내서 제 눈으로 과연 상관이 정말 없는지 확인해보고싶었습니다. 왼쪽이 공시지가, 오른쪽이 미세먼지 농도에 관한 그림입니다.

folium 라이브러리를 이용한 지도시각화 코드가 궁금하시다면

```py geo = '/gdrive/My Drive/Data Science/강의노트/20201005-1009_LS_DS_project week1/Seoul1.geojson' # 서울시 중심부의 위도, 경도 center = [37.541, 126.986] # center를 중심으로 하고 zoom 단계에 해당하는 맵 생성 map3 = folium.Map(location = center, tiles = 'Cartodb Positron', detect_retina=True, zoom_start=11) # Choropleth 레이어를 만들고, 맵 m에 추가 folium.Choropleth(geo_data=geo, data=final, columns=('행정동코드', '미세먼지(㎍/㎥)'), key_on='feature.properties.adm_cd2', fill_color='RdPu', legend_name='Concentration of fine dust', ).add_to(map3) map3.save('map3.html') map3 ```

선형적인 관계가 있으면 두 그림이 같은 경향을 보이거나 대비되는 모습을 보여야 하는데 아닌 것을 보면 확실히 연관성이 없다는 것을 알 수 있었습니다.

하지만 여태까지 고생한게 얼만데 이렇게 끝낼 수는 없잖아요? 그래서 저는 기왕 전처리해서 밑작업을 끝내놓은 김에 센서데이터를 이용해서 미세먼지 농도가 짙어질 때, 기온이나 자외선, 습도 등의 다른센서데이터는 어떤 경향을 보이는지 알아봤습니다.

그러기 위해 미세먼지 농도를 기준으로 정렬하여 상위 다섯개 도시를 뽑아봤습니다.

folium 지도시각화 & 마커 표시하기

```py # 미세먼지 상위 5개 도시 geo = '/gdrive/My Drive/Data Science/강의노트/20201005-1009_LS_DS_project week1/Seoul1.geojson' # 서울시 중심부의 위도, 경도 center = [37.541, 126.986] # center를 중심으로 하고 zoom 단계에 해당하는 맵 생성 map5 = folium.Map(location = center, tiles = 'Cartodb Positron', detect_retina=True, zoom_start=12) # Choropleth 레이어를 만들고, 맵 m에 추가 folium.Choropleth(geo_data=geo, data=final, columns=('행정동코드', '미세먼지(㎍/㎥)'), key_on='feature.properties.adm_cd2', fill_color='RdPu', legend_name='fine dust', ).add_to(map5) # 마커 객체 생성 marker1 = folium.Marker([37.537951, 127.005507], popup='Han-nam dong', icon=folium.Icon(color='blue')) marker2 = folium.Marker([37.566123, 126.986117], popup='Eul-ji-ro 2st', icon=folium.Icon(color='blue')) marker3 = folium.Marker([37.471441, 127.105509], popup='Se-gok dong 2st', icon=folium.Icon(color='blue')) marker4 = folium.Marker([37.573198, 127.003028], popup='Hyo-je dong', icon=folium.Icon(color='blue')) marker5 = folium.Marker([37.555363, 127.001871], popup='Jang Chung dong 2st', icon=folium.Icon(color='blue')) # 마커 추가 marker1.add_to(map5) marker2.add_to(map5) marker3.add_to(map5) marker4.add_to(map5) marker5.add_to(map5) map5.save('map5.html') map5 ```

그리고 이 다섯개의 도시를 각각 바 그래프로 그려서 미세먼지의 농도에 따른 경향을 살펴봤어요.

상위도시 5개 추리기 및 바그래프로 그리기

```py # 미세먼지농도 상위 5개 지역 #최종데이터에서 미세먼지농도를 기준으로 내림차순, 5개 뽑아 top_dust로 선언 top_dust = final.sort_values(by='미세먼지(㎍/㎥)', ascending=False).head(5) #최종데이터에서 그래프로 시각화 할 컬럼 선택하여 데이터프레임 생성 top_dust = top_dust[['미세먼지(㎍/㎥)', '법정동명', '진동_z 최대(g)', '자외선(UVI)','조도(lux)', '초미세먼지(㎍/㎥)', '상대습도( %)']] #top5 데이터프레임의 법정동명을 인덱스로 지정 top_dust = top_dust.set_index('법정동명') plt.figure(figsize=(12, 8), dpi=120) plt.subplot(3,3,1) plt.bar(top_dust.index, top_dust['미세먼지(㎍/㎥)'], color='#86A99F') plt.xlabel('법정동') plt.ylabel('미세먼지농도') plt.title('Top5 별 미세먼지농도') plt.subplot(3,3,2) plt.bar(top_dust.index, top_dust['초미세먼지(㎍/㎥)'], color='#86A99F') plt.xlabel('법정동') plt.ylabel('초미세먼지농도') plt.title('Top5 별 초미세먼지농도') plt.subplot(3,3,3) plt.bar(top_dust.index, top_dust['진동_z 최대(g)'], color='#86A99F') plt.xlabel('법정동') plt.ylabel('최대 진동') plt.title('Top5 별 최대진동') plt.subplot(3,3,4) plt.bar(top_dust.index, top_dust['자외선(UVI)'], color='#86A99F') plt.xlabel('법정동') plt.ylabel('자외선') plt.title('Top5 별 자외선') plt.subplot(3,3,5) plt.bar(top_dust.index, top_dust['조도(lux)'], color='#86A99F') plt.xlabel('법정동') plt.ylabel('조도') plt.title('Top5 별 조도') plt.subplot(3,3,6) plt.bar(top_dust.index, top_dust['상대습도( %)'], color='#86A99F') plt.xlabel('법정동') plt.ylabel('상대습도') plt.title('Top5 별 상대습도') plt.tight_layout() plt.show() ```

사실 분석을 시작하기 전에는 특정한 요인, 즉 측정기간동안 미세먼지가 심했던 지역에서는 공사를 했다던지, 행사가 열렸다던지 등의 특별한 이슈가 있을 것 같았고 이런 이슈가 있었다면 진동이나 소음 등의 측정값에서 그 결과를 볼 수 있을 것이라고 판단했거든요? 하지만 시각화를 해보니 미세먼지와 초미세먼지만 약간 비슷한 경향을 보일 뿐, 미세먼지와 다른 요소들간에는 특이점을 찾을 수 없었어요. 가지고있는 데이터를 통해서 얻을 수 있는 인사이트는 크게 없었던 것 같아서 과외로 구글링을 통하여 조사도 해봤지만 공사가 있었거나 행사가 열렸다는 내용을 특별히 발견할 수는 없었죠.

전체적으로 해당 분석을 돌이켜보면.. 조사한 시점 기준으로 미세먼지 농도와 공시지가가 상관이 있는지 여부는 알 수 있었지만 미세먼지의 농도와 공시지가가 서로 어떤 영향을 미치는지는 분석할 수 없어 아쉬웠습니다. 미세먼지 농도와 공시지가가 서로 어떤 영향을 주고받는지를 분석하려면 같은 기간의 미세먼지 농도의 변동율, 그리고 공시지가의 변동율이 필요했는데 미세먼지데이터는 올 4월부터 제공되기 시작했고 공시지가는 1년단위로 한번의 데이터밖에 없어서 변동율을 구할 수가 없었거든요. 시간을 너무 많이 사용하고나서야 내가 원하는 정보를 얻기위한 데이터가 중분치 않다는 것을 깨달아서 데이터셋을 변경할 생각도 하지 못헀어요. 하지만 추후에 데이터가 충분해지면 변동율을 이용한 분석을 다시 해봐도 괜찮을 것 같다는 생각을 했습니다. 원했던 인사이트들을 얻지 못해서 잠시 허무하긴 했는데 첫 시도부터 만족스럽긴 힘들테니까요. 다음에는 어떻게 하면 좋겠다는 팁을 얻었다는 그 자체로 의미가 있었다고 생각하려고 합니다.(안그러면 허무해서 잠도 못잘 것 같아요.) 추후에는 더욱 흥미로운 프로젝트를 소개해보겠습니다. 긴 글을 읽어주셔서 고맙습니다.