호쌤
호쌤 Just For Fun

[Python 데이터 시각화] 코로나19 선별진료소 분포 지도시각화

크리에이티브 커먼즈 라이선스 ITPAPER(호쌤,쭈쌤)에 의해 작성된 ≪[Python 데이터 시각화] 코로나19 선별진료소 분포 지도시각화≫은(는) 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
이 라이선스의 범위 이외의 이용허락을 얻기 위해서는 leekh4232@gmail.com으로 문의하십시오.

[Python 데이터 시각화] 코로나19 선별진료소 분포 지도시각화

코로나19로 인한 사회적 거리두기가 시행되는 동안 갑작스럽게 얻은 휴가 아닌 휴가를 보냈었습니다. 그 동안 이 시국을 반영한 학습 예제를 만들어보고 싶다는 생각이 들어서 공공데이터 포털의 선별진료소 위치 데이터 파일을 내려받아 시각화 예제를 구성해 보았습니다.

#01. 필요한 패키지 가져오기

1
2
3
4
from IPython.display import SVG   # jupyter 상에서 SVG 이미지를 표시하기 위한 패키지
from bs4 import BeautifulSoup     # TAG로부터 원하는 내용을 추출하는 클래스 -> SVG 이미지의 핸들링을 위함
from pandas import DataFrame
from pandas import read_csv

#02. 데이터 수집

공공데이터 포털에 공개된 2020년 03월 05일자 자료

1
2
df = read_csv("http://itpaper.co.kr/demo/py/clinic_20200305.csv", encoding="euc-kr")
df
▶ 출력결과
연번 검체채취 가능여부 시도 시군구 의료기관명 주소 대표 전화번호
0 1 Y 서울 강남구 강남구보건소 서울특별시 강남구 선릉로 668 (삼성동) 02-3423-5555
1 2 Y 서울 강남구 삼성서울병원 서울특별시 강남구 일원로 81 (일원동, 삼성의료원) 02-3410-2114
2 3 Y 서울 강남구 연세대학교의과대학강남세브란스병원 서울특별시 강남구 언주로 211, 강남세브란스병원 (도곡동) 02-2019-3114
3 4 Y 서울 강동구 강동경희대학교의대병원 서울특별시 강동구 동남로 892 (상일동) 02-440-7000
4 5 Y 서울 강동구 강동구보건소 서울특별시 강동구 성내로 45 (성내동) 02-3425-8565
... ... ... ... ... ... ... ...
601 602 Y 제주 제주시 중앙병원 제주특별자치도 제주시 월랑로 91-0 (이호이동,중앙병원) 064-786-7000
602 603 Y 대구 달서구 달서구보건소 관할 자동차 이동형(Drive-thru) 임시선별진료소 대구 달서구 학산로 140 달서구노인종합복지관 053-667-5618
603 604 Y 대구 달성군 달성군보건소 관할 자동차 이동형(Drive-thru) 임시선별진료소 대구 달성군 현풍읍 현풍로6길 5 도깨비시장 053-668-3333
604 605 Y 대구 동구 동구보건소 관할 자동차 이동형(Drive-thru) 임시선별진료소 대구 동구 율하동 율하체육공원박주영축구장 053-662-3200
605 606 Y 대구 서구 서구보건소 관할 자동차 이동형(Drive-thru) 임시선별진료소 대구 서구 당산로 403 서구 구민운동장 053-663-3111

606 rows × 7 columns

#03. 데이터 전처리 및 정제

필요한 필드만 추출하기

검체채취가 가능한 병원의 시,도와 병원이름만 추출한다.

1
2
df2 = df.query("`검체채취 가능여부` == 'Y'").filter(['시도', '의료기관명'])
df2
▶ 출력결과
시도 의료기관명
0 서울 강남구보건소
1 서울 삼성서울병원
2 서울 연세대학교의과대학강남세브란스병원
3 서울 강동경희대학교의대병원
4 서울 강동구보건소
... ... ...
601 제주 중앙병원
602 대구 달서구보건소 관할 자동차 이동형(Drive-thru) 임시선별진료소
603 대구 달성군보건소 관할 자동차 이동형(Drive-thru) 임시선별진료소
604 대구 동구보건소 관할 자동차 이동형(Drive-thru) 임시선별진료소
605 대구 서구보건소 관할 자동차 이동형(Drive-thru) 임시선별진료소

566 rows × 2 columns

#04. 데이터 분석 - 시도별 집계

그룹별 집계

1
2
결과df = df2.groupby(['시도']).count()
결과df
▶ 출력결과
의료기관명
시도
강원 34
경기 103
경남 49
경북 49
광주 9
대구 22
대전 13
부산 34
서울 57
세종 2
울산 12
인천 29
전남 59
전북 26
제주 6
충남 31
충북 31

컬럼이름 변경

1
2
결과집계df = 결과df.rename(columns={'의료기관명': '의료기관수'})
결과집계df
▶ 출력결과
의료기관수
시도
강원 34
경기 103
경남 49
경북 49
광주 9
대구 22
대전 13
부산 34
서울 57
세종 2
울산 12
인천 29
전남 59
전북 26
제주 6
충남 31
충북 31

인덱스 이름 변경

csv파일에서 사용되는 지역명과 svg 지도에 명시되어 있는 지역명이 서로 다르기 때문에 서로 지역명을 동일하게 맵핑하는 작업이 필요하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
index_dict = {'강원': '강원도',
            '경기': '경기도',
            '경남': '경상남도',
            '경북': '경상북도',
            '광주': '광주광역시',
            '대구': '대구광역시',
            '대전': '대전광역시',
            '부산': '부산광역시',
            '서울': '서울특별시',
            '세종': '세종특별자치시',
            '울산': '울산광역시',
            '인천': '인천광역시',
            '전남': '전라남도',
            '전북': '전라북도',
            '제주': '제주특별자치도',
            '충남': '충청남도',
            '충북': '충청북도'}

최종df = 결과집계df.rename(index=index_dict)
최종df
▶ 출력결과
의료기관수
시도
강원도 34
경기도 103
경상남도 49
경상북도 49
광주광역시 9
대구광역시 22
대전광역시 13
부산광역시 34
서울특별시 57
세종특별자치시 2
울산광역시 12
인천광역시 29
전라남도 59
전라북도 26
제주특별자치도 6
충청남도 31
충청북도 31

#05. 데이터 시각화

1) SVG 파일 열기

위키미디어에서 Korea districts.svg 키워드로 검색하여 서울 지도 이미지를 내려받아 map_korea.svg라는 이름으로 작업 폴더에 추가

svg

https://commons.wikimedia.org/wiki/File:District_map_of_South_Korea_2013.png

혹은 다음의 URL에서 내려받을 수 있습니다. http://itpaper.co.kr/demo/py/map_korea.svg

1
2
3
4
5
map_svg = None
with open('res/map_korea.svg', 'r', encoding='utf-8') as f:
    map_svg = f.read()
    
SVG(map_svg)
▶ 출력결과

svg

2) 지도 시각화에 필요한 준비 과정

사용할 색상값 (단계별로 6개 색상 준비)

1
2
colors = ['#F1EEF6', '#D4B9DA', '#C994C7', '#DF65B9', '#DD1C77', '#980043']
colors
▶ 출력결과
1
['#F1EEF6', '#D4B9DA', '#C994C7', '#DF65B9', '#DD1C77', '#980043']

svg 데이터 로드

한국 svg 파일의 데이터 구조는 이전 포스팅에 자세히 제시되어 있으니 여기서는 생략합니다.

1
soup = BeautifulSoup(map_svg)

id 속성을 갖는 <g>태그와 <path>태그 추출

1
glist = soup.select("svg > g[id], svg > path[id]")

3) 지도 시각화 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
for item in glist:
    if item['id'] not in 최종df.index:
        continue
        
    # item['id'] --> 지도에서 뽑아낸 id
    # 최종df에서 인덱스 이름이 지도에서 뽑아낸 id와 일치하는 행의 의료기관수를 추출
    count = 최종df.loc[ item['id'], '의료기관수' ]
    print(item['id'], " >> ", count)
    
    # 복지시설 수에 따라 단계값 설정 (단계는 색상값의 수에 따름)
    if count > 75:   color_index = 5
    elif count > 60: color_index = 4
    elif count > 45: color_index = 3
    elif count > 30: color_index = 2
    elif count > 15: color_index = 1
    else:            color_index = 0
        
    if 'fill' in item.attrs:
        item['fill'] = colors[color_index]
    else:  
        # 현재 요소(item)의 하위 항목들에게 색상을 적용해야 한다.
        for p in item.select('g, path'):
            if 'fill' in p.attrs:
                p['fill'] = colors[color_index]
            

선별진료소svg = soup.prettify()
▶ 출력결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
서울특별시  >>  57
인천광역시  >>  29
경기도  >>  103
강원도  >>  34
충청북도  >>  31
대전광역시  >>  13
충청남도  >>  31
제주특별자치도  >>  6
경상북도  >>  49
대구광역시  >>  22
울산광역시  >>  12
경상남도  >>  49
부산광역시  >>  34
전라북도  >>  26
광주광역시  >>  9
전라남도  >>  59
세종특별자치시  >>  2

svg

Rating:

크리에이티브 커먼즈 라이선스 ITPAPER(호쌤,쭈쌤)에 의해 작성된 ≪[Python 데이터 시각화] 코로나19 선별진료소 분포 지도시각화≫은(는) 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
이 라이선스의 범위 이외의 이용허락을 얻기 위해서는 leekh4232@gmail.com으로 문의하십시오.

comments powered by Disqus