Programing/Python

세무민의 SVG 도전! [2] : 이미지에 색을 입혀보기!

세기루민 2020. 11. 26. 16:10
728x90

기본적으로 데이터 가공을 끝낸 상태입니다.

 

sg-moomin.tistory.com/35

 

세무민의 SVG 도전! [1] : 쓸수 없는 공공데이터를 의미 있게 변환하기!

인턴 중 파싱을 돌리면서 남은 시간을 뭐하면서 보낼지 고민하다가 전에 했던 시각화를 기록으로 남기는걸 선택했다. 우선 SVG를 만드는 것을 목표로 진행 할 예정! 추가적으로 양이 너무 많으면

sg-moomin.tistory.com

위의 포스팅에서 가공하는 것을 진행했습니다.

 

그렇다면 이제 가공된 데이터를 이용해서 이미지에 색을 입혀보겠습니다.

 

사용할 이미지입니다. 

 

파일을 업로드하려고 했는데... 티스토리에서 파일 업로드 방법을 모르겠네요...

.

서울 지도 이미지는 구글에서 찾으면 나옵니다.

 

찾은지 좀 오래된 이미지라서 어디있는지 가물가물하네요..ㅎ

 

이런 지도에 대한 이미지를 Atom이라는 프로그램을 이용해서 확인해보면!

숫자값과 id값으로 구분되어서 xml형식으로 구성되어 있는 걸 확인!

 

이제 위의 그림에 색을 입히는 작업을 진행할 예정입니다.

 

결론부터 말하자면!

색을 입혀서 이런 디자인으로 변신완료!

 

화재와 유사한 붉은 계열로 입혔습니다.

 

이제 코드를 봐볼까요?

 

import pandas as pd
import numpy as np 
rea = pd.read_excel('소방장비현황_서울특별시.xlsx')

우선 DataFrame과 함수를 이용할 수 있도록 pandas와 numpy를 임폴트 해줍니다.

 

추가적으로 저번 포스팅에서 완성시킨 엑셀파일을 rea 파일에서 불러옵니다.

 

불러오면 이런 테이블을 확인할 수 있습니다.

 

import csv
from bs4 import BeautifulSoup
svg = open('서울특별시.svg','r').read()

CSV 파일을 사용할 수 있도록 임폴트해주고 

 

BeautifulSoup를 임폴트를 하면서 bs4로 사용하겠다고 선언합니다..

 

여기서 BeautifulSoup란 HTML 및 XML 문서 를 구문 분석하기위한 Python 패키지입니다

 

마지막으로 위에 서울특별시 지도인 svg파일을 호출하면 끝!

 

출력해보면 그림이 아닌 이렇게 숫자로 결과가 나오는걸 확인할 수 있습니다.

 

결과값이 아직 정리가 안된 것처럼 보일 수 있으나 xml 형식이라는 점!

 

soup = BeautifulSoup(svg)

beautifulSoup를 이용해서 svg문서를 구문을 분석해봅시다!

 

이제 조금 xml 문서같죠?

 

자세히 보다보면 <path> 테그를 볼 수 있습니다.

 

이 테그에 있는 값들을 이용하기 위해서 

 

paths = soup.findAll('path')

 

path에 대한 값들 모두 찾아서 paths라는 변수에 넣어줍니다.

 

이렇게 path에 대한 값들만 가져온 것을 확인할 수 있습니다.

 

이제 값들에서 추출할 수 있는 값들을 찾아보겠습니다.

 

위의 그림처럼 자세히 보면 id값들을 확인할 수 있습니다.

 

해당 id값들에 대해서 어떤 값들이 있는지 확인해보죠!

 

trans_list=[]
for i in paths:
    trans_list.append(i['id'])
    
trans_list

반복문을 돌려서 해당 id가 있는지 확인하고 id에 대한 값들을 trans_list에 담아서 출력해줍니다.

 

이처럼 id에 대한 값들을 확인할 수 있습니다.

 

이 값들을 이제 전에 만들었던 엑셀에 id와 유사한지 확인하면 되겠죠?

 

rea = rea.sort_values(by='소방장비',ascending=True)
rea = rea.set_index('소방장비')
rea = rea.reset_index()
rea = rea.drop([0,15,19,28])
rea = rea.set_index('소방장비')
rea = rea.reset_index()

확인하기 위해서 우선적으로 DataFrame을 id와 일치하도록 가공해줍니다.

 

참고로 가공하는 건 자신이 가지고 있는 Data에 따라서 달라질 수 있다는 점!

 

위처럼 테이블을 정리해준 후!

 

 

rea.loc[0, ['소방장비']] = 'Gangnam-gu'
rea.loc[1, ['소방장비']] = 'Gangdong-gu'
rea.loc[2, ['소방장비']] = 'Gangbuk-gu'
rea.loc[3, ['소방장비']] = 'Gangseo-gu'
rea.loc[4, ['소방장비']] = 'Gwanak-gu'
rea.loc[5, ['소방장비']] = 'Gwangjin-gu'
rea.loc[6, ['소방장비']] = 'Guro-gu'
rea.loc[7, ['소방장비']] = 'Geumcheon-gu'
rea.loc[8, ['소방장비']] = 'Nowon-gu'
rea.loc[9, ['소방장비']] = 'Dobong-gu'
rea.loc[10, ['소방장비']] = 'Dongdaemun-gu'
rea.loc[11, ['소방장비']] = 'Dongjak-gu'
rea.loc[12, ['소방장비']] = 'Mapo-gu'
rea.loc[13, ['소방장비']] = 'Seodaemun-gu'
rea.loc[14, ['소방장비']] = 'Seocho-gu'
rea.loc[15, ['소방장비']] = 'Seongdong-gu'
rea.loc[16, ['소방장비']] = 'Seongbuk-gu'
rea.loc[17, ['소방장비']] = 'Songpa-gu'
rea.loc[18, ['소방장비']] = 'Yangcheon-gu'
rea.loc[19, ['소방장비']] = 'Yeongdeungpo-gu_1_'
rea.loc[20, ['소방장비']] = 'Yongsan-gu'
rea.loc[21, ['소방장비']] = 'Eunpyeong-gu'
rea.loc[22, ['소방장비']] = 'Jongno-gu'
rea.loc[23, ['소방장비']] = 'Jungnang-gu'
rea.loc[24, ['소방장비']] = 'Jung-gu'
rea = rea.rename(columns={'소방장비':'COUNTY','합계':'NUMBER'})

ID값에 일치하도록 변경해줍니다.

 

마지막으로 컬럼까지 변경해주면 끝!

 

이 작업을 하기 위해서는 일단 테이블에 있는 index값과 id값을 하나씩 확인해봤다...

 

즉 노가다....

 

노가다 작업을 끝내고 이런 테이블을 확인할 수 있다.

 

이제 이 테이블에 색을 입혀주면 끝!

 

색을 입혀줄 때 크기별로 다르게 입혀주려고 노력했지만 값이 대부분 20이라서 변화가 크게 없다는 아쉬움...

 

그래도 마저 진행해보면!

rea = rea.sort_values(by='COUNTY',ascending=True)
rea = rea.set_index('COUNTY')
rea.to_csv('서울특별시_값변경_svg.csv', encoding='ms949')

 

일단 이렇게 열심히 만든 테이블을 CSV로 저장해주고

 

reader = csv.reader(open('서울특별시_값변경_svg.csv','r'))

다시 호출해준다.

 

이제는 SVG에 있는 이미지 별로 색을 입혀주는 작업을 진행할껀데 단순하고 쉽습니다.

 

방법은 해당 reader의 값을 정리해서 크기별로 색을 부여해주면 끝!

 

counter={}
counts_only=[]
min_value = 100;
max_value = 0;
past_header = False

for row in reader:        
    try:
        colorId = row[0]
        count = float(row[1].strip())
        counter[colorId] = count
        counts_only.append(count)
    except:
        pass

반복문을 이용해서 reader라는 csv파일에 데이터를 counts_only라는 배열에 하나씩 넣어줍니다. 

 

데이터를 넣을 때 소수형태로 넣어주는 건 포인트!

 

colors=['#F6EEEE','#FFD3D3','#FF7F7F', '#FF5E5E','#FF3F3F','#FF0000']
path_style = 'font-size:12px;fill-rule:nonzero;stroke:#FFFFFF;stroke-opacity:1;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;
              stroke-linecap:butt;marker-start:none;stroke-linejoin:bevel;fill:'

데이터 정리가 완료되면 이제 6개의 색을 선택해주고 

 

path_style이라는 값에는 SVG에서 표현하는 그림의 크기와 같이 디자인적인 요소를 수정해줍니다.

 

for p in paths:
    if p['id']:
        try:
            count=counter[p['id']]
        except:
            continue
            
        if count> 70:
            color_class=5
        elif count > 60:
            color_class=4
        elif count > 50:
            color_class=3
        elif count > 40:
            color_class=2
        elif count > 30:
            color_class=1
        elif count > 20:
            color_class=0
        
        color = colors[color_class]
        p['style'] = path_style+color



file=open('서울특별시_소방장비_시각화.svg','w')

for i in soup:
    file.write('%s\n' %soup)

file.close()

마지막으로 반복문을 이용해서 크기별로 색을 구분해줍니다.

 

반복문이 끝나면 해당 값을 SVG파일로 저장하면 끝!

저장까지 완료되구 이렇게 파일로 저장된 걸 확인할 수 있습니다.

 

파일을 확인해보면 처음에 보여준 핑크한 지도를 확인할 수 있습니다.

 

이번 포스팅에서는 데이터를 정형화하고 SVG를 이용해서 이미지에 색을 입히는 작업을 했습니다.

 

다음에는 더 흥미로은 포스팅으로 찾아오겠습니다! 

 

728x90