데이터 분석¶
- 데이터 정보 : 2019년도 서울에 위치하고 있는 주유소의 위치정보 및 일간 유가
(1) 고급휘발유 0인 값 108256개 / 실내등유 0인 값 110560개 / 전체 데이터 181714개
즉 고급휘발유와 실내등유를 보유하지 않은 주유소가 많다.
(2) 휘발유나 경유가 0인 데이터는 전체 데이터 대비 비율이 적기때문에 바로 삭제처리
(3) 도로명 column 추가
(4) 웹 데이터 크롤링
(5) 상,하반기 결합
(6) 기간 컬럼 dataTime으로 형변환 > 년 월 일 요일 컬럼 생성
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
import platform
from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus'] = False
if platform.system() == 'Darwin':
rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
path = "c:/Windows/Fonts/malgun.ttf"
font_name = font_manager.FontProperties(fname=path).get_name()
rc('font', family=font_name)
else:
print('Unknown system... sorry~~~~')
[웹 데이터 크롤링]
# 한글문제 해결
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
import platform
path = 'c:/Windows/Fonts/malgun.ttf'
from matplotlib import font_manager, rc
if platform.system() == 'Darwin':
rc('font', family = 'AppleGothic')
elif platform.system() == 'Windows':
font_name = font_manager.FontProperties(fname=path).get_name()
rc('font', family=font_name)
else:
print('Unknown system... sorry~~~')
1. 데이터 불러오기¶
상반기 주유소 판매 데이터 불러오기¶
first = pd.read_csv('../data/2019년 상반기 주유소 판매가격.csv',encoding='cp949')
first
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
90585 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20190626 | GS칼텍스 | 셀프 | 0 | 1529 | 1389 | 0 |
90586 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20190627 | GS칼텍스 | 셀프 | 0 | 1529 | 1389 | 0 |
90587 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20190628 | GS칼텍스 | 셀프 | 0 | 1529 | 1389 | 0 |
90588 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20190629 | GS칼텍스 | 셀프 | 0 | 1529 | 1389 | 0 |
90589 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20190630 | GS칼텍스 | 셀프 | 0 | 1529 | 1389 | 0 |
90590 rows × 11 columns
second = pd.read_csv('../data/2019년 하반기 주유소 판매가격.csv',encoding='cp949')
second
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190701 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190702 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190703 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190704 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190705 | SK에너지 | 셀프 | 1777 | 1577 | 1477 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
91119 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191227 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91120 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191228 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91121 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191229 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91122 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191230 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91123 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191231 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
91124 rows × 11 columns
# 상반기 판매가격 데이터 프레임 결측치 조회
first.isna().sum()
번호 0
지역 0
상호 0
주소 0
기간 0
상표 0
셀프여부 0
고급휘발유 0
휘발유 0
경유 0
실내등유 0
dtype: int64
# 하반기 판매가격 데이터 프레임 결측치 조회
second.isna().sum()
번호 0
지역 0
상호 0
주소 0
기간 0
상표 0
셀프여부 0
고급휘발유 0
휘발유 0
경유 0
실내등유 0
dtype: int64
[웹 데이터 크롤링]
from selenium import webdriver
pip install selenium
Requirement already satisfied: selenium in c:\anaconda3\lib\site-packages (3.141.0)
Requirement already satisfied: urllib3 in c:\anaconda3\lib\site-packages (from selenium) (1.25.11)
Note: you may need to restart the kernel to use updated packages.
#네이버에 접속
driver = webdriver.Chrome('chromedriver')
driver.get('http://naver.com')
# BeautifulSoup를 이용해서 페이지 내용 읽어오기
from bs4 import BeautifulSoup
html = driver.page_source # 현재 Selenium이 접근한 페이지 소스를 넘겨 받는다.
soup = BeautifulSoup(html, 'html.parser')
driver.get('http://www.opinet.co.kr/searRgSelect.do')
driver.get('http://www.opinet.co.kr/searRgSelect.do')
# 종로구라는 글자가 보이는 리스트 박스의 XPath를 이용하여 element를 찾고 gu_list_raw 변수에 저장한다.
gu_list_raw = driver.find_element_by_xpath('''//*[@id="SIGUNGU_NM0"]''')
# 구 리스트는 find_elements_by_tag_name으로 option이라는 태그를 찾으면 된다.
gu_list = gu_list_raw.find_elements_by_tag_name('option')
gu_names = [option.get_attribute('value') for option in gu_list]
gu_names.remove('')
gu_names
['가평군',
'고양시',
'고양시덕양구',
'고양시일산동구',
'고양시일산서구',
'과천시',
'광명시',
'광주시',
'구리시',
'군포시',
'김포시',
'남양주시',
'동두천시',
'부천시',
'성남시',
'성남시분당구',
'성남시수정구',
'성남시중원구',
'수원시',
'수원시권선구',
'수원시영통구',
'수원시장안구',
'수원시팔달구',
'시흥시',
'안산시',
'안산시단원구',
'안산시상록구',
'안성시',
'안양시',
'안양시동안구',
'안양시만안구',
'양주시',
'양평군',
'여주시',
'연천군',
'오산시',
'용인시',
'용인시기흥구',
'용인시수지구',
'용인시처인구',
'의왕시',
'의정부시',
'이천시',
'파주시',
'평택시',
'포천시',
'하남시',
'화성시']
#gu_names에서 첫번째 것을 한번 시험 삼아 입력해보자.
element = driver.find_element_by_id('SIGUNGU_NM0')
element.send_keys(gu_names[0])
#조회버튼의 Xpath를 찾아서 클릭
xpath ='''//*[@id="searRgSelect"]/span'''
element_sel_gu = driver.find_element_by_xpath(xpath).click()
# #엑셀 저장 버튼을 눌러서 엑셀 내용으로 저장하자.
# xpath = '''//*[@id="glopopd_excel"]/span'''
# element_get_excel = driver.find_element_by_xpath(xpath).click()
# import time
# from tqdm import tqdm_notebook
# for gu in tqdm_notebook(gu_names):
# element = driver.find_element_by_id('SIGUNGU_NM0')
# element.send_keys(gu)
# time.sleep(2)
# xpath ='''//*[@id="searRgSelect"]/span'''
# element_sel_gu = driver.find_element_by_xpath(xpath).click()
# time.sleep(1)
# xpath = '''//*[@id="glopopd_excel"]/span'''
# element_get_excel = driver.find_element_by_xpath(xpath).click()
# time.sleep(1)
# 드라이버를 닫고, 이제 저장된 엑셀 파일로 셀프 주유소가 실제로 저렴한지 여부를 확인해 보자.
driver.close()
- 구별 주유 가격에 대한 데이터의 정리 다운받은 25개의 엑셀 파일을 이전처럼 read를 이용하여 읽으면 25줄을 입력해야지만 모두 읽을 수 있지만 파이썬의 glob 모듈을 사용하면 손쉽게 열 수 있다.
from glob import glob
# 지역*.xls는 지역으로 시작하면서 확장자가 xls인 파일들
glob('./주유소위치폴더/지역*.xls')
['./주유소위치폴더\\지역_위치별(주유소) (1).xls',
'./주유소위치폴더\\지역_위치별(주유소) (10).xls',
'./주유소위치폴더\\지역_위치별(주유소) (11).xls',
'./주유소위치폴더\\지역_위치별(주유소) (12).xls',
'./주유소위치폴더\\지역_위치별(주유소) (13).xls',
'./주유소위치폴더\\지역_위치별(주유소) (14).xls',
'./주유소위치폴더\\지역_위치별(주유소) (15).xls',
'./주유소위치폴더\\지역_위치별(주유소) (16).xls',
'./주유소위치폴더\\지역_위치별(주유소) (17).xls',
'./주유소위치폴더\\지역_위치별(주유소) (18).xls',
'./주유소위치폴더\\지역_위치별(주유소) (19).xls',
'./주유소위치폴더\\지역_위치별(주유소) (2).xls',
'./주유소위치폴더\\지역_위치별(주유소) (20).xls',
'./주유소위치폴더\\지역_위치별(주유소) (21).xls',
'./주유소위치폴더\\지역_위치별(주유소) (22).xls',
'./주유소위치폴더\\지역_위치별(주유소) (23).xls',
'./주유소위치폴더\\지역_위치별(주유소) (24).xls',
'./주유소위치폴더\\지역_위치별(주유소) (25).xls',
'./주유소위치폴더\\지역_위치별(주유소) (3).xls',
'./주유소위치폴더\\지역_위치별(주유소) (4).xls',
'./주유소위치폴더\\지역_위치별(주유소) (5).xls',
'./주유소위치폴더\\지역_위치별(주유소) (6).xls',
'./주유소위치폴더\\지역_위치별(주유소) (7).xls',
'./주유소위치폴더\\지역_위치별(주유소) (8).xls',
'./주유소위치폴더\\지역_위치별(주유소) (9).xls',
'./주유소위치폴더\\지역_위치별(주유소).xls']
# station_files 변수에 각 엑셀 파일의 경로와 이름을 리스트로 저장
stations_files = glob('./주유소위치폴더/지역*.xls')
stations_files
['./주유소위치폴더\\지역_위치별(주유소) (1).xls',
'./주유소위치폴더\\지역_위치별(주유소) (10).xls',
'./주유소위치폴더\\지역_위치별(주유소) (11).xls',
'./주유소위치폴더\\지역_위치별(주유소) (12).xls',
'./주유소위치폴더\\지역_위치별(주유소) (13).xls',
'./주유소위치폴더\\지역_위치별(주유소) (14).xls',
'./주유소위치폴더\\지역_위치별(주유소) (15).xls',
'./주유소위치폴더\\지역_위치별(주유소) (16).xls',
'./주유소위치폴더\\지역_위치별(주유소) (17).xls',
'./주유소위치폴더\\지역_위치별(주유소) (18).xls',
'./주유소위치폴더\\지역_위치별(주유소) (19).xls',
'./주유소위치폴더\\지역_위치별(주유소) (2).xls',
'./주유소위치폴더\\지역_위치별(주유소) (20).xls',
'./주유소위치폴더\\지역_위치별(주유소) (21).xls',
'./주유소위치폴더\\지역_위치별(주유소) (22).xls',
'./주유소위치폴더\\지역_위치별(주유소) (23).xls',
'./주유소위치폴더\\지역_위치별(주유소) (24).xls',
'./주유소위치폴더\\지역_위치별(주유소) (25).xls',
'./주유소위치폴더\\지역_위치별(주유소) (3).xls',
'./주유소위치폴더\\지역_위치별(주유소) (4).xls',
'./주유소위치폴더\\지역_위치별(주유소) (5).xls',
'./주유소위치폴더\\지역_위치별(주유소) (6).xls',
'./주유소위치폴더\\지역_위치별(주유소) (7).xls',
'./주유소위치폴더\\지역_위치별(주유소) (8).xls',
'./주유소위치폴더\\지역_위치별(주유소) (9).xls',
'./주유소위치폴더\\지역_위치별(주유소).xls']
2. 데이터 결합¶
# 상반기와 하반기 데이터를 상하로 결합
df=pd.concat([first,second],ignore_index=True)
df
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
181709 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191227 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181710 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191228 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181711 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191229 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181712 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191230 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181713 | A0032659 | 서울 중랑구 | 지에스칼텍스㈜ 소망주유소 | 서울 중랑구 망우로 475 | 20191231 | GS칼텍스 | 셀프 | 0 | 1540 | 1389 | 1100 |
181714 rows × 11 columns
[웹 데이터 크롤링]
# concat 명령으로 폴더내의 자료들을 합친다.
tmp_raw = []
for file_name in stations_files:
tmp = pd.read_excel(file_name, header=2)
tmp_raw.append(tmp)
station_raw = pd.concat(tmp_raw)
station_raw.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 537 entries, 0 to 39
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 지역 537 non-null object
1 상호 537 non-null object
2 주소 537 non-null object
3 상표 537 non-null object
4 전화번호 537 non-null object
5 셀프여부 537 non-null object
6 고급휘발유 537 non-null object
7 휘발유 537 non-null object
8 경유 537 non-null object
9 실내등유 537 non-null object
dtypes: object(10)
memory usage: 46.1+ KB
station_raw.head()
지역 | 상호 | 주소 | 상표 | 전화번호 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 서울특별시 | (주)보성 세곡주유소 | 서울 강남구 헌릉로 731 (세곡동) | SK에너지 | 02-445-6870 | Y | - | 1435 | 1235 | - |
1 | 서울특별시 | GS칼텍스(주)직영 산성주유소 | 서울 강남구 헌릉로 730 | GS칼텍스 | 02-2226-4963 | Y | - | 1445 | 1245 | - |
2 | 서울특별시 | 방죽주유소 | 서울 강남구 밤고개로 215 (율현동) | GS칼텍스 | 02-459-3434 | Y | - | 1459 | 1259 | - |
3 | 서울특별시 | 오일프러스 셀프 | 서울 강남구 남부순환로 2651 (도곡동) | SK에너지 | 02-3462-5100 | Y | 1612 | 1463 | 1259 | - |
4 | 서울특별시 | 현대오일뱅크 도곡셀프주유소 | 서울 강남구 남부순환로 2718 (도곡2동) | 현대오일뱅크 | 02-529-5101 | Y | 1627 | 1473 | 1269 | - |
3. 데이터 가공 및 분석¶
# 데이터 프레임 정보 조회
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 181714 entries, 0 to 181713
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 번호 181714 non-null object
1 지역 181714 non-null object
2 상호 181714 non-null object
3 주소 181714 non-null object
4 기간 181714 non-null int64
5 상표 181714 non-null object
6 셀프여부 181714 non-null object
7 고급휘발유 181714 non-null int64
8 휘발유 181714 non-null int64
9 경유 181714 non-null int64
10 실내등유 181714 non-null int64
dtypes: int64(5), object(6)
memory usage: 15.3+ MB
# 상표 컬럼의 고유값 조회
df['상표'].unique()
array(['SK에너지', 'GS칼텍스', 'S-OIL', '현대오일뱅크', '알뜰주유소', 'NH-OIL', '알뜰(ex)',
'자가상표'], dtype=object)
# 지역 컬럼의 고유값 조회
df['지역'].unique()
array(['서울 강남구', '서울 강동구', '서울 강북구', '서울 강서구', '서울 관악구', '서울 광진구',
'서울 구로구', '서울 금천구', '서울 노원구', '서울 도봉구', '서울 동대문구', '서울 동작구',
'서울 마포구', '서울 서대문구', '서울 서초구', '서울 성동구', '서울 성북구', '서울 송파구',
'서울 양천구', '서울 영등포구', '서울 용산구', '서울 은평구', '서울 종로구', '서울 중구',
'서울 중랑구'], dtype=object)
# 지역 컬럼의 값을 이용하여 시와 구를 분리
df['시'] = df['지역'].str.split(' ').str[0]
df['구'] = df['지역'].str.split(' ').str[1]
df.head()
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | 시 | 구 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울 | 강남구 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울 | 강남구 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울 | 강남구 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울 | 강남구 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울 | 강남구 |
# 시 컬럼의 서울을 서울특별시로 변환
df['시'] = '서울특별시'
df.head()
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | 시 | 구 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190101 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190102 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190103 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190104 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 20190105 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
# 기간 컬럼을 datetime 형식으로 변경
df['기간'] = pd.to_datetime(df['기간'],format='%Y%m%d')
df.head()
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | 시 | 구 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-01 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-02 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-03 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-04 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-05 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 |
# 기간 컬럼에서 dt 타입을 이용하여 년, 월, 일, 요일 컬럼 생성
df['년'] = df['기간'].dt.year
df['월'] = df['기간'].dt.month
df['일'] = df['기간'].dt.day
df['요일'] = df['기간'].dt.day_name()
df.head()
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | 시 | 구 | 년 | 월 | 일 | 요일 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-01 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 1 | Tuesday |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-02 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 2 | Wednesday |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-03 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 3 | Thursday |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-04 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 4 | Friday |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-05 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 5 | Saturday |
df[df['상호'] == '(주)동하힐탑셀프주유소']
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | 시 | 구 | 년 | 월 | 일 | 요일 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-01 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 1 | Tuesday |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-02 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 2 | Wednesday |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-03 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 3 | Thursday |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-04 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 4 | Friday |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-05 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 5 | Saturday |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
90769 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-12-27 | SK에너지 | 셀프 | 1802 | 1657 | 1495 | 0 | 서울특별시 | 강남구 | 2019 | 12 | 27 | Friday |
90770 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-12-28 | SK에너지 | 셀프 | 1802 | 1657 | 1495 | 0 | 서울특별시 | 강남구 | 2019 | 12 | 28 | Saturday |
90771 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-12-29 | SK에너지 | 셀프 | 1802 | 1657 | 1495 | 0 | 서울특별시 | 강남구 | 2019 | 12 | 29 | Sunday |
90772 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-12-30 | SK에너지 | 셀프 | 1802 | 1657 | 1495 | 0 | 서울특별시 | 강남구 | 2019 | 12 | 30 | Monday |
90773 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-12-31 | SK에너지 | 셀프 | 1802 | 1657 | 1495 | 0 | 서울특별시 | 강남구 | 2019 | 12 | 31 | Tuesday |
365 rows × 17 columns
# 휘발유 가격이 비싼 5개 판매가격을 출력하세요.
df['휘발유'].sort_values(ascending=False).head()
177210 2356
177216 2356
177217 2356
177211 2356
177212 2356
Name: 휘발유, dtype: int64
# 휘발유 가격이 저렴한 5개 판매가격을 출력하세요. (단 휘발유가 0원인 데이터는 제외)
df[df['휘발유'] != 0]['휘발유'].sort_values().head(5)
13148 1255
82475 1260
82474 1260
82476 1260
82998 1265
Name: 휘발유, dtype: int64
df1 = df.copy()
df.head()
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | 시 | 구 | 년 | 월 | 일 | 요일 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-01 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 1 | Tuesday |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-02 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 2 | Wednesday |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-03 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 3 | Thursday |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-04 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 4 | Friday |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-05 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 5 | Saturday |
[웹 데이터 크롤링]
# 원하는 컬럼만 가지고 오고 이름도 다시 정의해서 stations 변수에 저장
# 이 단원에서는 휘발유만 다루겠다.
stations = pd.DataFrame({'Oil_store': station_raw['상호'],
'주소': station_raw['주소'],
'가격': station_raw['휘발유'],
'셀프': station_raw['셀프여부'],
'상표': station_raw['상표']
})
stations.head()
Oil_store | 주소 | 가격 | 셀프 | 상표 | |
---|---|---|---|---|---|
0 | (주)보성 세곡주유소 | 서울 강남구 헌릉로 731 (세곡동) | 1435 | Y | SK에너지 |
1 | GS칼텍스(주)직영 산성주유소 | 서울 강남구 헌릉로 730 | 1445 | Y | GS칼텍스 |
2 | 방죽주유소 | 서울 강남구 밤고개로 215 (율현동) | 1459 | Y | GS칼텍스 |
3 | 오일프러스 셀프 | 서울 강남구 남부순환로 2651 (도곡동) | 1463 | Y | SK에너지 |
4 | 현대오일뱅크 도곡셀프주유소 | 서울 강남구 남부순환로 2718 (도곡2동) | 1473 | Y | 현대오일뱅크 |
# 추가로 주소에서 구 이름만 추출하자.
# 빈칸을 기준으로 분리 후 2번째 단어 선택
stations['구'] = [eachAddress.split()[1] for eachAddress in stations['주소']]
stations.head()
Oil_store | 주소 | 가격 | 셀프 | 상표 | 구 | |
---|---|---|---|---|---|---|
0 | (주)보성 세곡주유소 | 서울 강남구 헌릉로 731 (세곡동) | 1435 | Y | SK에너지 | 강남구 |
1 | GS칼텍스(주)직영 산성주유소 | 서울 강남구 헌릉로 730 | 1445 | Y | GS칼텍스 | 강남구 |
2 | 방죽주유소 | 서울 강남구 밤고개로 215 (율현동) | 1459 | Y | GS칼텍스 | 강남구 |
3 | 오일프러스 셀프 | 서울 강남구 남부순환로 2651 (도곡동) | 1463 | Y | SK에너지 | 강남구 |
4 | 현대오일뱅크 도곡셀프주유소 | 서울 강남구 남부순환로 2718 (도곡2동) | 1473 | Y | 현대오일뱅크 | 강남구 |
# head만 보기에는 문제 없으나 500여개의 데이터가 어떤 상태인지 확인하기 쉽지 않다.
# unique() 검사 수행
stations['구'].unique()
array(['강남구', '도봉구', '동대문구', '동작구', '마포구', '서대문구', '서초구', '성동구', '성북구',
'송파구', '양천구', '강동구', '영등포구', '용산구', '은평구', '종로구', '중구', '중랑구',
'강북구', '강서구', '관악구', '광진구', '구로구', '금천구', '노원구'], dtype=object)
# 가격 컬럼의 unique를 구해보자.
stations['가격'].unique()
array(['1435', '1445', '1459', '1463', '1473', '1479', '1485', '1488',
'1495', '1505', '1518', '1525', '1527', '1528', '1533', '1538',
'1548', '1550', '1626', '1628', '1697', '1788', '1847', '1856',
'1918', '1935', '1938', '1953', '1971', '1988', '2075', '-', 1412,
1414, 1419, 1425, 1435, 1438, 1448, 1449, 1453, 1475, 1479, 1498,
'1425', '1437', '1439', '1442', '1458', '1465', '1468', '1469',
'1477', '1497', '1498', '1499', '1599', '1610', 1459, 1489, 1509,
1565, '1457', '1466', '1467', '1557', '1689', '1757', 1434, 1439,
1444, 1455, 1462, 1464, 1467, 1474, 1478, '1379', '1449', '1464',
'1475', '1508', '1539', '1571', '1595', '1662', '1867', '1888',
'1942', 1427, 1458, 1465, 1516, 1518, 1545, 1635, 1705, 1748, 1755,
1398, 1428, 1437, 1442, 1457, 1499, 1440, 1443, 1454, 1463, 1468,
1473, 1477, 1487, 1497, 1638, 1698, 1399, 1408, 1418, 1423, 1460,
1480, 1519, 1694, 1697, 1476, 1488, 1494, 1495, 1505, 1515, 1547,
1548, 1578, 1963, '1384', '1389', '1399', '1409', '1415', '1417',
'1429', '1438', '1440', '1448', '1455', '1494', '1748', '1868',
'1940', '1950', '1954', '1979', 1568, 1718, 1720, 1764, 1829, 1849,
1858, 1863, 1898, 1990, 1998, 2189, '1424', '1428', '1434', '1447',
'1478', 1510, 1517, 1540, 1888, 1948, 1995, '1648', '1758', '1828',
'1848', '1869', '1985', '2099', '2129', '2270', 1445, 1447, 1456,
1508, 1409, 1429, 1387, 1395, 1405, 1416, 1491, 1528, 1538, 1615,
1758, '1487', '1489', 1469, 1529, 1537, 1485, 1496, 1942, '1530',
'1598'], dtype=object)
휘발유나 경유가 0인 데이터는 전체 데이터 대비 비율이 적기때문에 바로 삭제처리
drop_df = df1[(df1['휘발유'] == 0) | (df1['경유'] ==0)]
print(f'기존데이터: {df1.shape[0]}개\n휘발유나 경유가 0인 데이터: {drop_df.shape[0]}개')
df1 = df1.drop(index=drop_df.index)
print(f'삭제 후 데이터: {df1.shape[0]}개')
기존데이터: 181714개
휘발유나 경유가 0인 데이터: 68개
삭제 후 데이터: 181646개
도로명 column 추가
df1['도로명'] = df1['주소'].str.split(' ').str[2]
df1.head()
번호 | 지역 | 상호 | 주소 | 기간 | 상표 | 셀프여부 | 고급휘발유 | 휘발유 | 경유 | 실내등유 | 시 | 구 | 년 | 월 | 일 | 요일 | 도로명 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-01 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 1 | Tuesday | 논현로 |
1 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-02 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 2 | Wednesday | 논현로 |
2 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-03 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 3 | Thursday | 논현로 |
3 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-04 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 4 | Friday | 논현로 |
4 | A0006039 | 서울 강남구 | (주)동하힐탑셀프주유소 | 서울 강남구 논현로 640 | 2019-01-05 | SK에너지 | 셀프 | 1673 | 1465 | 1365 | 0 | 서울특별시 | 강남구 | 2019 | 1 | 5 | Saturday | 논현로 |
[웹 데이터 크롤링]
# 숫자가 아닌 '-' 문자가 끼어있다.
stations[stations['가격']=='-']
Oil_store | 주소 | 가격 | 셀프 | 상표 | 구 | |
---|---|---|---|---|---|---|
38 | 삼성주유소 | 서울 강남구 삼성로 521 (삼성동) | - | N | SK에너지 | 강남구 |
39 | 동우주유소 | 서울특별시 강남구 봉은사로 311 (논현동) | - | N | SK에너지 | 강남구 |
21 | 신성주유소 | 서울 동대문구 장한로 29 (장안동) | - | N | 현대오일뱅크 | 동대문구 |
12 | 서강주유소 | 서울 마포구 독막로 134 (창전동) | - | N | SK에너지 | 마포구 |
35 | 전당앞주유소 | 서울 서초구 남부순환로 2391 (서초동) | - | N | SK에너지 | 서초구 |
30 | 성락주유소 | 서울 영등포구 가마산로 414 (신길동) | - | Y | S-OIL | 영등포구 |
16 | 삼융주유소 | 서울 은평구 수색로 299 (수색동) | - | N | SK에너지 | 은평구 |
10 | 에스씨(주) 역전주유소 | 서울 중구 퇴계로 15 | - | N | GS칼텍스 | 중구 |
15 | CJ대한통운㈜ 신림주유소 | 서울 관악구 남부순환로 1515 (신림동) | - | N | GS칼텍스 | 관악구 |
14 | 양지진흥개발(주)상계주유소 | 서울 노원구 노해로 527 (상계동) | - | N | SK에너지 | 노원구 |
38 | 삼성주유소 | 서울 강남구 삼성로 521 (삼성동) | - | N | SK에너지 | 강남구 |
39 | 동우주유소 | 서울특별시 강남구 봉은사로 311 (논현동) | - | N | SK에너지 | 강남구 |
# '-' 문자가 포함된 데이터 제외시켜 버리기
stations = stations[stations['가격'] != '-']
stations.head()
Oil_store | 주소 | 가격 | 셀프 | 상표 | 구 | |
---|---|---|---|---|---|---|
0 | (주)보성 세곡주유소 | 서울 강남구 헌릉로 731 (세곡동) | 1435 | Y | SK에너지 | 강남구 |
1 | GS칼텍스(주)직영 산성주유소 | 서울 강남구 헌릉로 730 | 1445 | Y | GS칼텍스 | 강남구 |
2 | 방죽주유소 | 서울 강남구 밤고개로 215 (율현동) | 1459 | Y | GS칼텍스 | 강남구 |
3 | 오일프러스 셀프 | 서울 강남구 남부순환로 2651 (도곡동) | 1463 | Y | SK에너지 | 강남구 |
4 | 현대오일뱅크 도곡셀프주유소 | 서울 강남구 남부순환로 2718 (도곡2동) | 1473 | Y | 현대오일뱅크 | 강남구 |
# 가격을 float 형으로 변환한다.
stations['가격'] = [float(value) for value in stations['가격']]
# 25개의 엑셀을 합쳤기 때문에 index가 중복될 수 있다.
# reset_index 명령으로 인덱스를 처음부터 다시 기록하자.
# index라는 컬럼이 하나 더 생기는데 그 부분을 제거한다.
stations.reset_index(inplace=True)
del stations['index']
stations.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 525 entries, 0 to 524
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Oil_store 525 non-null object
1 주소 525 non-null object
2 가격 525 non-null float64
3 셀프 525 non-null object
4 상표 525 non-null object
5 구 525 non-null object
dtypes: float64(1), object(5)
memory usage: 24.7+ KB
Visualization¶
1) 기름 유형의 기간에 따른 가격 변동¶
- 목적: 기름 유형별 가격 변화 파악
- 시각화 채택 이유: 1년간 기름유형별 가격 등락 파악에 용이
plt.figure(figsize=(12,7))
aaa = df.pivot_table(values=['휘발유', '경유','고급휘발유','실내등유'], index='기간')
sns.lineplot(data=aaa, palette="tab10", linewidth=2.5)
plt.show()
2) 상표 및 셀프여부에 따른 분포 정리¶
- 목적: 서울시 내 각 정유사 및 주유유형별 분포를 확인하여 가장 대중화된 업체 및 주유형태 파악
- 시각화 채택 이유: 상표와 셀프여부에 따른 비중 파악에 용이하며, 자료 겹칩을 방지하기 위해 explode를 사용하여 가시성 증대
fig, ax = plt.subplots(1, 2, figsize=(15,7), dpi=300)
count_df = df1[['상호','상표','셀프여부']].drop_duplicates()
size = count_df['상표'].value_counts()
labels = count_df['상표'].value_counts().index
colors=plt.cm.Wistia(np.linspace(0,1,count_df['상표'].value_counts().shape[0]))
explode = [0,0,0,0,0,0.1,0.2,0.3]
ax[0].pie(size, labels=labels, colors=colors, shadow=True, startangle=45, explode=explode,autopct='%.1f%%')
ax[0].set_title('상표별 데이터 분포',fontsize=20)
ax[0].legend()
size = count_df['셀프여부'].value_counts()
labels = count_df['셀프여부'].value_counts().index
colors = plt.cm.Pastel1(np.linspace(0, 1, 2))
explode = [0.01, 0.01]
ax[1].pie(size, labels=labels, colors=colors, shadow=True, startangle=45, explode=explode,autopct='%.1f%%')
ax[1].set_title('셀프여부 데이터 분포',fontsize=20)
ax[1].legend()
plt.tight_layout()
plt.show()
3) 휘발유와 경유 가격의 분포¶
-
목적 : 1년간 유가가 어느 가격대에 많이 분포되어 있는지 확인
-
시각화 채택 이유 : 서울시의 1년간의 유가 정보를 통해 앞으로의 값에 대한 가능성의 정도를 추정하기에 용이
-
시각화를 통해 얻은 정보 : 휘발유와 경유의 분포 모양이 비슷하며 가우시안 분포를 어느정도 따라간다.
휘발유는 1400~1600원 경유는 1300~1500원 정도를 유지하였다.
fig, ax = plt.subplots(2, 1, figsize=(15,7), dpi=300)
sns.distplot(df1['휘발유'], color = 'pink',ax=ax[0])
ax[0].set_title('휘발유', fontsize = 20)
ax[0].set_xlabel('가격', fontsize = 0)
ax[0].set_ylabel('density', fontsize = 16)
sns.distplot(df1['경유'], color = 'pink',ax=ax[1])
ax[1].set_title('경유', fontsize = 20)
ax[1].set_xlabel('가격', fontsize = 16)
ax[1].set_ylabel('density', fontsize = 16)
plt.tight_layout()
plt.show()
4) 월간 고급휘발유와 실내등유의 평균 가격¶
- 목적: 시간의 흐름에 따른 고급휘발유와 실내등유의 가격 변동 파악
- 시각화 채택 이유: 어떤 시즌에 유가의 변동이 일어나는지 파악하는데 용이 - 시각화를 통해 얻은 정보 : 고급휘발유의 가격은 S/S 시즌에 높아지고 F/W 시즌에 낮아진다. 반면에 실내등유는 여름철에 가격이 낮아지고 겨울철에 높아진다. -> 수요가 많아지면서 가격또한 높아짐을 알 수 있다.
# 월별 고급휘발유, 실내등유 평균가격
data = df1[(df['고급휘발유'] != 0) | (df['실내등유'] !=0)]
data = data.pivot_table(index='월',values=['고급휘발유','실내등유'],aggfunc='mean').reset_index()
fig, ax = plt.subplots(1, 2, figsize=(10,5), dpi=300)
sns.barplot(x = data['월'], y = data['고급휘발유'], palette = 'pastel',ax=ax[0])
ax[0].set_xlabel(xlabel = '월', fontsize = 12)
ax[0].set_ylabel(ylabel = '평균가격', fontsize = 12)
ax[0].set_title(label = '고급휘발유', fontsize = 15)
sns.barplot(x = data['월'], y = data['실내등유'], palette = 'pastel',ax=ax[1])
ax[1].set_xlabel(xlabel = '월', fontsize = 12)
ax[1].set_ylabel(ylabel = '평균가격', fontsize = 12)
ax[1].set_title(label = '실내등유', fontsize = 15)
plt.tight_layout()
plt.show()
5) 1년간 각 지역별 휘발유와 경유의 평균 가격¶
-
목적: 어느 지역이 가격대가 높게 형성되었고 또 어떤 지역이 가격대가 낮은지 확인
-
시각화 채택 이유: 가격대별로 지역들을 정렬하여 한눈에 각 지역의 유가를 파악하는데에 용이
fig, ax = plt.subplots(2, 1, figsize=(15,7), dpi=300, sharex=True)
data = df1.pivot_table(index='구',values=['휘발유','경유']).sort_values(by='휘발유',ascending=False).reset_index()
data
구 | 경유 | 휘발유 | |
---|---|---|---|
0 | 중구 | 1835.953011 | 1976.948052 |
1 | 용산구 | 1755.083886 | 1887.254609 |
2 | 종로구 | 1696.179182 | 1838.554945 |
3 | 강남구 | 1577.271600 | 1713.328332 |
4 | 마포구 | 1555.951075 | 1690.628367 |
5 | 성동구 | 1446.205749 | 1583.659561 |
6 | 서초구 | 1456.007124 | 1577.705147 |
7 | 강동구 | 1442.151680 | 1577.487784 |
8 | 영등포구 | 1442.211041 | 1568.256215 |
9 | 노원구 | 1402.993780 | 1531.221551 |
10 | 서대문구 | 1392.777321 | 1528.925416 |
11 | 구로구 | 1381.307984 | 1525.413845 |
12 | 송파구 | 1394.908481 | 1518.951058 |
13 | 관악구 | 1395.139450 | 1518.635029 |
14 | 동작구 | 1392.197748 | 1513.717111 |
15 | 양천구 | 1379.040346 | 1513.057730 |
16 | 성북구 | 1376.006440 | 1508.315789 |
17 | 동대문구 | 1366.267426 | 1507.402202 |
18 | 도봉구 | 1370.153055 | 1494.393741 |
19 | 광진구 | 1357.036899 | 1490.597054 |
20 | 강서구 | 1357.277517 | 1489.164266 |
21 | 은평구 | 1351.908372 | 1481.964026 |
22 | 금천구 | 1347.144787 | 1477.121992 |
23 | 중랑구 | 1331.235747 | 1468.997552 |
24 | 강북구 | 1328.962611 | 1454.131601 |
sns.barplot(x = data['구'], y = data['휘발유'], palette = 'husl',ax=ax[0])
ax[0].set_xlabel(xlabel = '사라져', fontsize = 0)
ax[0].set_ylabel(ylabel = '평균가격', fontsize = 15)
ax[0].set_title(label = '휘발유', fontsize = 15)
sns.barplot(x = data['구'], y = data['경유'], palette = 'husl',ax=ax[1])
ax[1].set_xlabel(xlabel = '지역', fontsize = 15)
ax[1].set_ylabel(ylabel = '평균가격', fontsize = 15)
ax[1].set_title(label = '경유', fontsize = 15)
plt.tight_layout()
plt.show()
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
C:\anaconda3\lib\site-packages\pandas\core\indexes\base.py in get_loc(self, key, method, tolerance)
3079 try:
-> 3080 return self._engine.get_loc(casted_key)
3081 except KeyError as err:
pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()
pandas\_libs\index.pyx in pandas._libs.index.IndexEngine.get_loc()
pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()
pandas\_libs\hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()
KeyError: '휘발유'
The above exception was the direct cause of the following exception:
KeyError Traceback (most recent call last)
<ipython-input-77-96bb90c02cbe> in <module>
----> 1 sns.barplot(x = data['구'], y = data['휘발유'], palette = 'husl',ax=ax[0])
2 ax[0].set_xlabel(xlabel = '사라져', fontsize = 0)
3 ax[0].set_ylabel(ylabel = '평균가격', fontsize = 15)
4 ax[0].set_title(label = '휘발유', fontsize = 15)
5
C:\anaconda3\lib\site-packages\pandas\core\frame.py in __getitem__(self, key)
3022 if self.columns.nlevels > 1:
3023 return self._getitem_multilevel(key)
-> 3024 indexer = self.columns.get_loc(key)
3025 if is_integer(indexer):
3026 indexer = [indexer]
C:\anaconda3\lib\site-packages\pandas\core\indexes\base.py in get_loc(self, key, method, tolerance)
3080 return self._engine.get_loc(casted_key)
3081 except KeyError as err:
-> 3082 raise KeyError(key) from err
3083
3084 if tolerance is not None:
KeyError: '휘발유'
6) 지역의 상표별 주유소 개수¶
- 목적: 지역별로 진출한 정유사 파악
- 시각화 채택 이유: 서울시 모든 지역별로 눈에 띄게 시장을 장악한 정유업체 파악에 용이
data = df1[['구','상호','상표','셀프여부']].drop_duplicates()
data
구 | 상호 | 상표 | 셀프여부 | |
---|---|---|---|---|
0 | 강남구 | (주)동하힐탑셀프주유소 | SK에너지 | 셀프 |
181 | 강남구 | (주)만정에너지 | GS칼텍스 | 일반 |
362 | 강남구 | (주)보성 세곡주유소 | SK에너지 | 셀프 |
543 | 강남구 | (주)선진도곡주유소 | S-OIL | 일반 |
724 | 강남구 | (주)소모에너지엔테크놀러지 쎈트럴주유소 | GS칼텍스 | 일반 |
... | ... | ... | ... | ... |
157241 | 송파구 | 위례제일주유소 | S-OIL | 셀프 |
158498 | 송파구 | 현대오일뱅크㈜직영 잠실셀프주유소 | 현대오일뱅크 | 셀프 |
160206 | 양천구 | 가로공원주유소 | SK에너지 | 일반 |
162586 | 양천구 | 현대오일뱅크(주)직영 양천셀프주유소 | 현대오일뱅크 | 셀프 |
173235 | 은평구 | 번개셀프주유소 | 자가상표 | 셀프 |
528 rows × 4 columns
data = df1[['구','상호','상표','셀프여부']].drop_duplicates()
plt.figure(figsize = (25,8))
ax = sns.countplot(x = '구', data = data, palette = 'pastel',hue='상표')
ax.set_title(label = '각 지역의 상표별 주유소 개수', fontsize = 20)
ax.set_xlabel(xlabel = '지역', fontsize = 16)
ax.set_ylabel(ylabel = '개수', fontsize = 16)
plt.show()
7) 상표별 휘발유 분포¶
- 목적: 주유형태에 따른 상표별 점유율 파악
- 시각화 채택 이유: 많은 데이터의 분포와 범위를 한눈에 보기 쉽게 나타냄
fig, ax = plt.subplots(2, 1, figsize=(20,8), dpi=300)
sns.violinplot(data=df1, x="상표", y="휘발유", hue="셀프여부",
split=True, inner="quart", linewidth=1, palette="Set2",ax=ax[0]
)
ax[0].set_title('휘발유', fontsize=25)
ax[0].set_ylabel('분포',fontsize=20)
ax[0].set_xlabel('상표',fontsize=0)
sns.violinplot(data=df1, x="상표", y="경유", hue="셀프여부",
split=True, inner="quart", linewidth=1, palette="Set2",ax=ax[1]
)
ax[1].set_title('경유', fontsize=25)
ax[1].set_ylabel('분포',fontsize=20)
ax[1].set_xlabel('상표',fontsize=20)
plt.tight_layout()
plt.show()
8) 서울특별시 전체(일반/셀프) 주유소 분포¶
- 목적: 지역별 가장 많은 주유소를 갖고 있는 지역 파악
- 시각화 채택 이유: 주유소 갯수 데이터 크기를 내림차순으로 비교 용이
a = df1[['구','상호']].drop_duplicates()
a
구 | 상호 | |
---|---|---|
0 | 강남구 | (주)동하힐탑셀프주유소 |
181 | 강남구 | (주)만정에너지 |
362 | 강남구 | (주)보성 세곡주유소 |
543 | 강남구 | (주)선진도곡주유소 |
724 | 강남구 | (주)소모에너지엔테크놀러지 쎈트럴주유소 |
... | ... | ... |
89866 | 중랑구 | 재원에너지㈜ 범아주유소 |
90047 | 중랑구 | 중랑교 |
90228 | 중랑구 | 지에스칼텍스㈜ 대원주유소 |
90409 | 중랑구 | 지에스칼텍스㈜ 소망주유소 |
157241 | 송파구 | 위례제일주유소 |
512 rows × 2 columns
unique = a['구'].value_counts()
plt.figure(figsize=(10,8))
plt.title('지역별 ')
sns.barplot(y=unique.index,x=unique.values, palette="deep")
<AxesSubplot:title={'center':'지역별 '}>
9) 각 지역의 셀프 여부별 주유소 개수¶
- 목적: 지역별 셀프여부에 따른 시장점유율 파악
- 시각화 채택 이유: 서울시 내 모든 지역에서 가시성 높은 셀프/일반 단 2개의 데이터 비교 용이
data = df1[['구','상호','상표','셀프여부']].drop_duplicates()
plt.figure(figsize = (25,8))
ax = sns.countplot(x = '구', data = data, palette = 'hls',hue='셀프여부')
ax.set_title(label = '각 지역의 셀프여부별 주유소 개수', fontsize = 20)
ax.set_xlabel(xlabel = '지역', fontsize = 16)
ax.set_ylabel(ylabel = '개수', fontsize = 16)
plt.show()
10) 월별 셀프여부에 따른 휘발유 분포¶
- 목적: 월별 주유 유형의 점유율 파악
- 시각화 채택 이유: 많은 데이터의 분포와 범위를 한눈에 보기 쉽게 나타냄
fig, ax = plt.subplots(2, 1, figsize=(15,7), dpi=300, sharex=True)
sns.violinplot(data=df1, x="월", y="휘발유", hue="셀프여부",
split=True, inner="quart", linewidth=1, palette="Set3",ax=ax[0]
) #특정 순서를 암시하지 않는, 그냥 고유한 색상이라고 볼 수 있기 때문니다.
ax[0].set_title('휘발유', fontsize=20)
ax[0].set_xlabel('월',fontsize=0)
ax[0].set_ylabel('분포',fontsize=15)
sns.violinplot(data=df1, x="월", y="경유", hue="셀프여부",
split=True, inner="quart", linewidth=1, palette="Set3",ax=ax[1]
)
ax[1].set_title('경유', fontsize=20)
ax[1].set_xlabel('월',fontsize=15)
ax[1].set_ylabel('분포',fontsize=15)
plt.tight_layout()
plt.show()
11) 셀프 주유소와 일반 주유소의 가격 분포¶
-
목적: 전반적인 데이터들의 결과를 보고 셀프, 일발 주유소의 차이점을 이해할수 있다.
-
시각화 채택 이유: boxplot으로 간편하게 셀프 컬럼을 기준으로 가격 분포를 확인할 수 있게 되었다. 코드의 결과를 보면 직사각형이 데이터의 대다수가 몰려 있는 곳이라는 것은 직관적으로 알 수 있다. 전반적으로 셀프 주유소인 경유가 가격이 낮게 되어 있다.
- 시각화 채택 이유: Swarmplot을 같이 그려보면 좀 더 확실히 데이터의 분포를 볼 수 있다. 셀프 주유소 말고 상표별 데이터를 확인했는데 SK에너지가 높은 가격대를 형성하는 주유소가 많았다. 전반적으로는 현대 오일뱅크가 4대 주유 브랜드 중에서는 저렴하다는 것을 확인할 수 있다.
stations
Oil_store | 주소 | 가격 | 셀프 | 상표 | 구 | |
---|---|---|---|---|---|---|
0 | (주)보성 세곡주유소 | 서울 강남구 헌릉로 731 (세곡동) | 1435.0 | Y | SK에너지 | 강남구 |
1 | GS칼텍스(주)직영 산성주유소 | 서울 강남구 헌릉로 730 | 1445.0 | Y | GS칼텍스 | 강남구 |
2 | 방죽주유소 | 서울 강남구 밤고개로 215 (율현동) | 1459.0 | Y | GS칼텍스 | 강남구 |
3 | 오일프러스 셀프 | 서울 강남구 남부순환로 2651 (도곡동) | 1463.0 | Y | SK에너지 | 강남구 |
4 | 현대오일뱅크 도곡셀프주유소 | 서울 강남구 남부순환로 2718 (도곡2동) | 1473.0 | Y | 현대오일뱅크 | 강남구 |
... | ... | ... | ... | ... | ... | ... |
520 | SK논현주유소 | 서울 강남구 논현로 747 (논현동) | 1938.0 | N | SK에너지 | 강남구 |
521 | (주)만정에너지 | 서울 강남구 봉은사로 433 (삼성동) | 1953.0 | N | GS칼텍스 | 강남구 |
522 | 학여울주유소 | 서울 강남구 남부순환로 3170 (일원2동) | 1971.0 | N | GS칼텍스 | 강남구 |
523 | (주)소모에너지엔테크놀러지 쎈트럴주유소 | 서울 강남구 삼성로 335 | 1988.0 | N | GS칼텍스 | 강남구 |
524 | 뉴서울(강남) | 서울 강남구 언주로 716 | 2075.0 | N | SK에너지 | 강남구 |
525 rows × 6 columns
stations.boxplot(column='가격', by='셀프', figsize=(12,8))
plt.figure(figsize=(12,8))
sns.boxplot(x='상표', y='가격', hue='셀프', data=stations, palette='Set3')
plt.figure(figsize=(12,8))
sns.boxplot(x='상표', y='가격', data=stations, palette='Set3')
sns.swarmplot(x='상표', y='가격', data=stations, color='.6')
plt.show()
결과¶
현대 오일뱅크, GS칼텍스, S-Oil, SK에너지 모두 셀프 주유소가 저렴하다. SK에너지는 그 중 가격대가 가장 높게 형성되어 있는 것을 알 수 있다.
pip install folium
Requirement already satisfied: folium in c:\anaconda3\lib\site-packages (0.12.0)
Requirement already satisfied: numpy in c:\anaconda3\lib\site-packages (from folium) (1.19.2)
Requirement already satisfied: branca>=0.3.0 in c:\anaconda3\lib\site-packages (from folium) (0.4.2)
Requirement already satisfied: requests in c:\anaconda3\lib\site-packages (from folium) (2.24.0)
Requirement already satisfied: jinja2>=2.9 in c:\anaconda3\lib\site-packages (from folium) (2.11.2)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in c:\anaconda3\lib\site-packages (from requests->folium) (1.25.11)
Requirement already satisfied: chardet<4,>=3.0.2 in c:\anaconda3\lib\site-packages (from requests->folium) (3.0.4)
Requirement already satisfied: idna<3,>=2.5 in c:\anaconda3\lib\site-packages (from requests->folium) (2.10)
Requirement already satisfied: certifi>=2017.4.17 in c:\anaconda3\lib\site-packages (from requests->folium) (2020.6.20)
Requirement already satisfied: MarkupSafe>=0.23 in c:\anaconda3\lib\site-packages (from jinja2>=2.9->folium) (1.1.1)
Note: you may need to restart the kernel to use updated packages.
pip install googlemaps
Requirement already satisfied: googlemaps in c:\anaconda3\lib\site-packages (4.4.2)
Requirement already satisfied: requests<3.0,>=2.20.0 in c:\anaconda3\lib\site-packages (from googlemaps) (2.24.0)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in c:\anaconda3\lib\site-packages (from requests<3.0,>=2.20.0->googlemaps) (1.25.11)
Requirement already satisfied: idna<3,>=2.5 in c:\anaconda3\lib\site-packages (from requests<3.0,>=2.20.0->googlemaps) (2.10)
Requirement already satisfied: chardet<4,>=3.0.2 in c:\anaconda3\lib\site-packages (from requests<3.0,>=2.20.0->googlemaps) (3.0.4)
Requirement already satisfied: certifi>=2017.4.17 in c:\anaconda3\lib\site-packages (from requests<3.0,>=2.20.0->googlemaps) (2020.6.20)
Note: you may need to restart the kernel to use updated packages.
# 지도를 그리기 위한 모듈 import
import json
import folium
import googlemaps
import warnings
warnings.simplefilter(action='ignore', category = FutureWarning)
# 이제 서울시에서 가장 주유 가격이 비싼 주유소를 보겠다.
stations.sort_values(by='가격', ascending=False).head(10)
Oil_store | 주소 | 가격 | 셀프 | 상표 | 구 | |
---|---|---|---|---|---|---|
343 | 서남주유소 | 서울 중구 통일로 30 | 2270.0 | N | SK에너지 | 중구 |
308 | 서계주유소 | 서울 용산구 청파로 367 (서계동) | 2189.0 | N | GS칼텍스 | 용산구 |
342 | 필동주유소 | 서울 중구 퇴계로 196 (필동2가) | 2129.0 | N | GS칼텍스 | 중구 |
341 | SK에너지(주) 퇴계로주유소 | 서울 중구 퇴계로 228 (필동2가) | 2099.0 | N | SK에너지 | 중구 |
524 | 뉴서울(강남) | 서울 강남구 언주로 716 | 2075.0 | N | SK에너지 | 강남구 |
37 | 뉴서울(강남) | 서울 강남구 언주로 716 | 2075.0 | N | SK에너지 | 강남구 |
306 | 한남지점 | 서울 용산구 한남대로21길 4 (한남동) | 1998.0 | N | SK에너지 | 용산구 |
307 | 에너비스 | 서울 용산구 한남대로 82 (한남동) | 1998.0 | N | SK에너지 | 용산구 |
332 | (주)대양씨앤씨 사직주유소 | 서울 종로구 사직로 65 (사직동) | 1998.0 | N | GS칼텍스 | 종로구 |
333 | (주)중앙에너비스 혜화주유소 | 서울 종로구 창경궁로35길 1 | 1998.0 | N | SK에너지 | 종로구 |
# 서울시에서 가장 주유 가격이 싼 주유소
stations.sort_values(by='가격', ascending=True).head(10)
Oil_store | 주소 | 가격 | 셀프 | 상표 | 구 | |
---|---|---|---|---|---|---|
114 | 만남의광장주유소 | 서울 서초구 양재대로12길 73-71 | 1379.0 | Y | 알뜰(ex) | 서초구 |
265 | 남서울고속주유소 | 서울 영등포구 가마산로 367 (대림동) | 1379.0 | Y | SK에너지 | 영등포구 |
266 | 도림주유소 | 서울 영등포구 도림로 343 (도림동) | 1384.0 | Y | 알뜰주유소 | 영등포구 |
373 | 화곡역주유소 | 서울 강서구 강서로 154 (화곡동) | 1387.0 | Y | 알뜰주유소 | 강서구 |
374 | 뉴신정주유소 | 서울 강서구 곰달래로 207(화곡동) | 1387.0 | N | 알뜰주유소 | 강서구 |
267 | (주)강서오일 | 서울 영등포구 도신로 151 | 1389.0 | N | 현대오일뱅크 | 영등포구 |
375 | 유턴주유소 | 서울 강서구 남부순환로 57 | 1395.0 | Y | 알뜰주유소 | 강서구 |
166 | 원천주유소 | 서울 성북구 돌곶이로 142 (장위동) | 1398.0 | N | 알뜰주유소 | 성북구 |
167 | 강산제2주유소 | 서울 성북구 보국문로 52 | 1398.0 | Y | 현대오일뱅크 | 성북구 |
168 | (주)삼표에너지 정릉주유소 | 서울 성북구 보국문로 35 (정릉동) | 1398.0 | Y | GS칼텍스 | 성북구 |
# pivot_table을 이용해서 구별 가격 정보로 변경하고 가격은 평균값으로 정리하자.
import numpy as np
gu_data = pd.pivot_table(stations, index=['구'], values=['가격'],
aggfunc=np.mean)
gu_data.head()
가격 | |
---|---|
구 | |
강남구 | 1624.868421 |
강동구 | 1532.500000 |
강북구 | 1430.461538 |
강서구 | 1475.454545 |
관악구 | 1468.600000 |
# # 서울시 구별 정보에 대해 지도로 표현하자. 평균적으로
# geo_path = './02. skorea_municipalities_geo_simple.json'
# geo_str = json.load(open(geo_path, encoding='utf-8'))
# map = folium.Map(location=[37.5502, 126.982], zoom_start=10.5,
# tiles='Stamen Toner')
# map.choropleth(geo_data = geo_str,
# data = gu_data,
# columns=[gu_data.index, '가격'],
# fill_color='PuRd', #PuRd, YlGnBu
# key_on='feature.id')
# map
4-6 서울시 주유 가격 상하위 10개 주유소 지도에 표기하기¶
# 주유 가격 상위 10개 주소를 oil_price_top10 이름으로 저장한다.
oil_price_top10 = stations.sort_values(by='가격', ascending=False).head(10)
oil_price_top10
Oil_store | 주소 | 가격 | 셀프 | 상표 | 구 | |
---|---|---|---|---|---|---|
343 | 서남주유소 | 서울 중구 통일로 30 | 2270.0 | N | SK에너지 | 중구 |
308 | 서계주유소 | 서울 용산구 청파로 367 (서계동) | 2189.0 | N | GS칼텍스 | 용산구 |
342 | 필동주유소 | 서울 중구 퇴계로 196 (필동2가) | 2129.0 | N | GS칼텍스 | 중구 |
341 | SK에너지(주) 퇴계로주유소 | 서울 중구 퇴계로 228 (필동2가) | 2099.0 | N | SK에너지 | 중구 |
524 | 뉴서울(강남) | 서울 강남구 언주로 716 | 2075.0 | N | SK에너지 | 강남구 |
37 | 뉴서울(강남) | 서울 강남구 언주로 716 | 2075.0 | N | SK에너지 | 강남구 |
306 | 한남지점 | 서울 용산구 한남대로21길 4 (한남동) | 1998.0 | N | SK에너지 | 용산구 |
307 | 에너비스 | 서울 용산구 한남대로 82 (한남동) | 1998.0 | N | SK에너지 | 용산구 |
332 | (주)대양씨앤씨 사직주유소 | 서울 종로구 사직로 65 (사직동) | 1998.0 | N | GS칼텍스 | 종로구 |
333 | (주)중앙에너비스 혜화주유소 | 서울 종로구 창경궁로35길 1 | 1998.0 | N | SK에너지 | 종로구 |
# 역시 하위 10개에 대해서도 oil_price_bottom10에 저장한다.
oil_price_bottom10 = stations.sort_values(by='가격', ascending=True).head(10)
oil_price_bottom10
Oil_store | 주소 | 가격 | 셀프 | 상표 | 구 | |
---|---|---|---|---|---|---|
114 | 만남의광장주유소 | 서울 서초구 양재대로12길 73-71 | 1379.0 | Y | 알뜰(ex) | 서초구 |
265 | 남서울고속주유소 | 서울 영등포구 가마산로 367 (대림동) | 1379.0 | Y | SK에너지 | 영등포구 |
266 | 도림주유소 | 서울 영등포구 도림로 343 (도림동) | 1384.0 | Y | 알뜰주유소 | 영등포구 |
373 | 화곡역주유소 | 서울 강서구 강서로 154 (화곡동) | 1387.0 | Y | 알뜰주유소 | 강서구 |
374 | 뉴신정주유소 | 서울 강서구 곰달래로 207(화곡동) | 1387.0 | N | 알뜰주유소 | 강서구 |
267 | (주)강서오일 | 서울 영등포구 도신로 151 | 1389.0 | N | 현대오일뱅크 | 영등포구 |
375 | 유턴주유소 | 서울 강서구 남부순환로 57 | 1395.0 | Y | 알뜰주유소 | 강서구 |
166 | 원천주유소 | 서울 성북구 돌곶이로 142 (장위동) | 1398.0 | N | 알뜰주유소 | 성북구 |
167 | 강산제2주유소 | 서울 성북구 보국문로 52 | 1398.0 | Y | 현대오일뱅크 | 성북구 |
168 | (주)삼표에너지 정릉주유소 | 서울 성북구 보국문로 35 (정릉동) | 1398.0 | Y | GS칼텍스 | 성북구 |
# google maps API용 key 입력
gmap_key = 'AIzaSyD5J0tdagg-KxXLNRhkD8kTImlcAmMV1Pk'
gmaps = googlemaps.Client(key=gmap_key)
gmaps.geocode(tmp_add)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-76-d5063ff21488> in <module>
----> 1 gmaps.geocode(tmp_add)
NameError: name 'tmp_add' is not defined
oil_price_top10
tmp_add = str(oil_price_top10['주소'][n]).split('(')[0]
tmp_add
gmaps.geocode(tmp_add)
# 주유 가격 상위 10개 주유소에 대해 위도, 경도 정보를 읽어오자.
# 구글 맵에서 검색할 수 없다든지 하는 문제로 에러가 나는 것에 대비해 try-except
# try 구문을 실행하다가 에러나면 except 구문에서 지정된 nan값을 저장
from tqdm import tqdm_notebook
lat = []
lng = []
for n in tqdm_notebook(oil_price_top10.index):
try:
tmp_add = str(oil_price_top10['주소'][n]).split('(')[0]
print('1')
tmp_map = gmaps.geocode(tmp_add)
print('2')
tmp_loc = tmp_map[0].get('geometry')
print('3')
lat.append(tmp_loc['location']['lat'])
print('4')
lng.append(tmp_loc['location']['lng'])
print('5')
except:
lat.append(np.nan)
lng.append(np.nan)
print('Here is nan !')
oil_price_top10['lat']=lat
oil_price_top10['lng']=lng
oil_price_top10
lat = []
lng = []
for n in tqdm_notebook(oil_price_bottom10.index):
try:
tmp_add = str(oil_price_bottom10['주소'][n]).split('(')[0]
tmp_map = gmaps.geocode(tmp_add)
tmp_loc = tmp_map[0].get('geometry')
lat.append(tmp_loc['location']['lat'])
lng.append(tmp_loc['location']['lng'])
except:
lat.append(np.nan)
lng.append(np.nan)
print('Here is nan !')
oil_price_bottom10['lat']=lat
oil_price_bottom10['lng']=lng
oil_price_bottom10
결과를 보면 '중구', '종로구'와 같은 서울 중심에 비싼 주유소가 몰려있고, '강북', '은평', '양천'과 같은 서울 바깥방향에 저렴한 주유소가 몰려 있다는 것을 알 수 있다.기름이 부족하다면 서울 안쪽으로 들어가기 전에 미리 넣고 가는 것이 좋다는 것을 알 수 있다.
# 위에서 혹시 nan값으로 처리된 부분이 있다면 , # notmul 명령을 이용해서 NaN이 아닐때만 지도에 표기하도록 한다. map = folium.Map(location=[37.5202, 126.975], zoom_start=10.5) for n in oil_price_top10.index: if pd.notnull(oil_price_top10['lat'][n]): folium.CircleMarker([oil_price_top10['lat'][n], oil_price_top10['lng'][n]], radius=15, color='#CD3181', fill_color='#CD3181').add_to(map) for n in oil_price_bottom10.index: if pd.notnull(oil_price_bottom10['lat'][n]): folium.CircleMarker([oil_price_bottom10['lat'][n], oil_price_bottom10['lng'][n]], radius=15, color='#3186cc', fill_color='#3186cc').add_to(map) map
'workSpace > PYTHON' 카테고리의 다른 글
[Matplot] Matplot Lib를 이용한 시각화 (0) | 2021.01.18 |
---|---|
[Pandas][Numpy][seaborn] 2019년 서울 특별시 아파트 실거래 분석 및 표 만들기 (0) | 2021.01.18 |
[ML] SVM - 지도학습 분류모델 실습 (0) | 2021.01.18 |
[ML] SVM - 지도학습 분류모델 (0) | 2021.01.18 |
[ML][DL] 전반적인 이해도 및 로직 설명, 자료 (0) | 2021.01.18 |