Mid_Project 전기차 충전소 예측

psy4072·2022년 10월 25일
0

Project

목록 보기
1/2
post-thumbnail

서울시 전기차 충전소는 어디에 몇 곳이 필요할까?

  • 2026년까지 전기차를 40만대까지 확대
  • 전기차 충전소 22만대 보급한다고 하는데 충분한가
  • 그러면 전기차 충전소는 어디에 얼마나 필요할까?
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import folium
import requests
import json
import plotly.express as px

# 지수표현식 제거하기
pd.options.display.float_format = '{:.5f}'.format

import koreanize_matplotlib
# 그래프에 retina display 적용
%config InlineBackend.figure_format = 'retina'

서울시 전기차

file_name = ("data/서울특별시 친환경자동차 현황.CSV")
raw = pd.read_csv(file_name, encoding='cp949')

raw = raw.loc[raw['연료'] == '전기', ['기준년월', '사용본거지시읍면동_행정동기준', '차명', '연료']]
raw = raw.rename(columns={"사용본거지시읍면동_행정동기준":"주소"})
raw = raw.dropna()

raw["구"] = raw["주소"].map(lambda x : x.split()[1])

서울시 구 별 전기차 수

df = raw.groupby("구")["차명"].count().sort_values(ascending=False).to_frame()
df = df.rename(columns={"차명" : "전기차수"})
df

# 구 별 전기차 top 5
explode = [0.1,0.05, 0.05,0.05,0.05]
plt.figure(figsize=(10,10))
plt.pie(ev_car_top5['전기차수'],
		labels=ev_car_top5.index, 
        explode=explode, 
        autopct='%.d%%')
plt.show()

# 서울시 전체 전기차 수 비율
wedgeprops = {'width': 0.7, 'edgecolor': 'w', 'linewidth': 1}
colors = ['#c1abff', '#d8e1c5', '#80afe5', '#ddadd0', '#ebbfea', '#84cec0', '#9acee9', '#d6c2b6', '#d48c9d', '#dcf6c5']
plt.figure(figsize=(10,10))
plt.pie(df['전기차수'], labels=df.index, autopct='%.d%%', colors = colors,
       shadow=True,
        wedgeprops=wedgeprops)
plt.title("서울시 전기차 수 비율")
plt.show()

서울시 총 전기차 수

df["전기차수"].sum()
=> 41673

서울시 전기차 충전소

ev_raw = pd.read_excel("Data/서울시충전기.xlsx")
ev_raw.head(2)
=>
	운영기관				충전소				지역		시군구	주소						충전용량
0	환경부(한국자동차환경협회)	DMC 산학협력연구센터	서울특별시	마포구	서울특별시 마포구 매봉산로 37	급속(100kW멀티)
1	환경부(한국자동차환경협회)	Park M (주차복합빌딩)	서울특별시	마포구	서울특별시 마포구 매봉산로 80	급속(200kW동시)

서울시 구 별 충전소 수

# 시군구로 count
ev_df = ev_raw.groupby("시군구")["충전소"].count().sort_values(ascending=False).to_frame()

# index 이름으로 시군구 -> 구 변경
ev_df.index = ev_df.index.set_names("구")
ev_df

# 구 별 전기차 충전소 pie chart 시각화
explode = [0.1,0.05, 0.05,0.05,0.05]
wedgeprops = {'width': 0.7, 'edgecolor': 'w', 'linewidth': 1}
colors = ['#c1abff', '#d8e1c5', '#80afe5', '#ddadd0', '#ebbfea', '#84cec0', '#9acee9', '#d6c2b6', '#d48c9d', '#dcf6c5']
plt.figure(figsize=(10,10))
plt.pie(ev_df['충전소'], labels=ev_df.index, autopct='%.d%%', colors = colors,
       shadow=True,
        wedgeprops=wedgeprops)
plt.title("구 별 전기차 충전소")
plt.show()

서울시 충전소 총 합계

ev_df["충전소"].sum()
=> 29556

전기차 수와 충전소 합치기

# index 공백 제거
ev_df.index = ev_df.index.str.strip()

df = df.merge(ev_df, left_index=True, right_index=True)
df

현재 충전소 당 전기차 시각화

df["현재충전소당전기차"] = df["전기차수"] / df["충전소"]

plt.figure(figsize=(20,6))
sns.barplot(data=df, x=df.index, y="현재충전소당전기차", ci=None).set_title("현재충전소당전기차")

  • 비율이 맞지 않은 상태
  • 이 비율대로 전기차 충전소를 늘리면 불균형 발생해 시민들의 불편 반발

미래 서울시 전기차 예상 목표 : 40만대

  • 각 구에 몇 대가 늘어나게 될까
  • 미래에 현재 비율로 전기차 충전소는 얼마나 필요할까
# 현재 전기차 수 / 충전소 수 / 전기차 대 충전소 비율
df["전기차수"].sum(), df['충전소'].sum(), df['충전소'].sum() / df['전기차수'].sum()
=> (41673, 29556, 0.7092361960981931)
# 필요한 충전소 수
ev_easy_count = round(400000 * (df["충전소"].sum() / df["전기차수"].sum()))
ev_easy_count
=> 283694

서울시 목표량과 비교

# 서울시 목표량
seoul_ev = 220000 + df['충전소'].sum()
seoul_ev
=> 249556

# 부족한 충전소 수 
round(400000 * (df['충전소'].sum() / df['전기차수'].sum())) - (220000 + df["충전소"].sum())
=> 34138

40만 대 도달, 각 구 별 전기차 수 예측

# 비율 * 40만대
df['미래전기차수'] = round((df['전기차수'] / df['전기차수'].sum()) * 400000).astype(int)
df

현재 충전소 1곳 당 전기차 수용 가능 최대-최소 수치 비교

ev_st_top = df['현재충전소당전기차'].sort_values(ascending=False).head(1).to_frame()
ev_st_tail = df['현재충전소당전기차'].sort_values(ascending=False).tail(1).to_frame()
aa = pd.concat([ev_st_top, ev_st_tail])
aa.plot(kind='bar', rot=0, title="충전소 1곳 당 전기차 수용가능 수치 최대-최소 차이 비교", figsize=(10,3))

현재 충전소 분포 비율기준으로 미래 충전소 수 예측

# 현재 기준 단순 예측
future_station = round((df["충전소"] / df["충전소"].sum()) * ev_easy_count).astype(int)

# pie chart 시각화
explode = [0.1,0.05, 0.05,0.05,0.05]
wedgeprops = {'width': 0.7, 'edgecolor': 'w', 'linewidth': 1}
colors = ['#c1abff', '#d8e1c5', '#80afe5', '#ddadd0', '#ebbfea', '#84cec0', '#9acee9', '#d6c2b6', '#d48c9d', '#dcf6c5']
plt.figure(figsize=(10,10))
plt.pie(ev_df['충전소'], labels=ev_df.index, autopct='%.d%%', colors = colors,
       shadow=True,
        wedgeprops=wedgeprops)
plt.title("미래 구 별 전기차 충전소 설치 개수 가정")
plt.show()

충전소 설치 예측을 어느 기준에 맞춰야 할까

1) 현재 주유소 분포

2) 인구 분포

  • 주유소는 기존 자동차 수에 대해 충분히 분포하고 있다고 가정
  • 전기차는 인구 밀도에도 영향이 있을 수 있다고 가정

서울시 총 인구 데이터

people = pd.read_csv("data/서울시인구데이터2021.csv", encoding="cp949")
# 전처리
people = people[["행정구역별(읍면동)", "2021"]].iloc[2:]
people = people.reset_index(drop=True)
people = people.rename(columns={"행정구역별(읍면동)":"구","2021":"인구"})
people = people.set_index("구")
people

# 숫자타입으로 변경
people['인구'] = people["인구"].astype(int)

# 시각화
plt.figure(figsize=(20,6))
sns.barplot(data=people, x=people.index, y="인구", ci=None).set_title("인구")

서울시 주유소 데이터

oil = pd.read_csv("data/서울시주유소.csv", encoding="cp949")
oil.head()
=>
	연번	자치구명	주유소명						주소
0	1	용산구	현대오일뱅크() 직영소월길주유소	서울특별시 용산구 소월로66
1	2	용산구	선익상사() 동자동주유소			서울특별시 용산구 한강대로 1046
2	3	용산구	현대오일뱅크㈜ 직영갈월동주유소		서울특별시 용산구 한강대로 322
3	4	용산구	서계주유소						서울특별시 용산구 청파로 367
4	5	용산구	㈜영원에너지 풍기주유소			서울특별시 용산구 원효로178
oil_df = oil.groupby("자치구명")[["주유소명"]].count()
oil_df.index = oil_df.index.set_names("구")
oil_df = oil_df.rename(columns={"주유소명":"주유소 수"})
oil_df

인구 데이터와 주유소 데이터 합치기

df_op = people.merge(oil_df, left_index=True, right_index=True)
df_op

전기차 & 충전소 & 인구 & 주유소 데이터 합치기

df = df_op.merge(df, left_index=True, right_index=True)
df

상관계수

df.corr()

# 히트맵 시각화
plt.figure(figsize=(15, 10))
sns.heatmap(df.corr(), cmap="Greens", annot=True)

중간 인사이트

  • 충전소의 수는 인구보다 주유소 분포가 더 상관관계 있다
  • 인구에 비례하기 보다는 주유소의 비율로 충전소를 늘리는 것이 더 유의미
  • 내연기관차 대비 얼마만큼의 주유소가 분포하는지 확인해보자

서울시 내연기관 자동차 데이터

car_raw = pd.read_csv("data/서울시자동차등록수.csv", encoding="cp949")
car_raw = car_raw[4:]
car_raw["구"] =  car_raw["행정동-연료별 분류"].map(lambda x : x.split()[1].strip())
car_df = car_raw[["구","경유","하이브리드(경유-전기)","하이브리드(휘발유-전기)","휘발유","휘발유(무연)","휘발유(유연)"]]
car_df

# 결측치 확인
car_df.isnull().sum()
=>0
경유                	3
하이브리드(경유-전기)     75
하이브리드(휘발유-전기)    22
휘발유              	12
휘발유(무연)           9
휘발유(유연)          89
dtype: int64
# 결측치 0 변경
car_df = car_df.fillna(0)

# 구 별로 묶어주기
car_df = car_df.groupby("구").sum()

car_df["휘발유자동차수"] = car_df.sum(axis=1).astype(int)
car_df

구 별 내연기관 자동차 수

car_df = car_df['휘발유자동차수']]
car_df

데이터 합치기

df = df.merge(car_df, left_index=True, right_index=True)
df

주유소 당 내연기관차 수

df["자동차당주유소비율"] = df["주유소 수"] / df["휘발유자동차수"] * 100
df

주유소 비율에 맞게 전기차 충전소 배치

# 서울시 목표 충전소 수 
seoul_ev
=> 249556
# 자동차 당 주유소비율로 전기차 충전소 예측

(df["자동차당주유소비율"] * df["미래전기차수"] * 37).sum()
=> 260029.803241865
df["주유소비율로본미래충전소개수"] = (df["자동차당주유소비율"] * df["미래전기차수"] * 37)
plt.figure(figsize=(20,6))
sns.barplot(data=df, x=df.index, y="주유소비율로본미래충전소개수", ci=None).set_title("주유소비율로본미래충전소개수")

df["미래충전소당전기차예측(주유소기준)"] = df["미래전기차수"] / df["주유소비율로본미래충전소갯수"]
df["미래충전소당전기차예측(주유소기준)"].to_frame()

# 주유소기준 미래 충전소 당 전기차 예측
plt.figure(figsize=(20,6))
sns.barplot(data=df, x=df.index, y="미래충전소당전기차예측(주유소기준)", ci=None).set_title("미래충전소당전기차예측(주유소기준)")

인구 비율로 충전소 늘린다면?

  • 인구 비율이 높은 쪽 충전소를 늘린다면 어떨까
df["인구비"] = df["인구"] / df["인구"].sum()

(df["인구비"] * df["미래전기차수"] * 13.7).sum()
=> 249381.5231770858

df["인구비율로본미래충전소개수"] = (df["인구비"] * df["미래전기차수"] * 13.7)

plt.figure(figsize=(20,6))
sns.barplot(data=df, x=df.index, y="인구비율로본미래충전소개수", ci=None).set_title("인구비율로본미래충전소개수")

df["미래충전소당전기차예측(인구기준)"] = df["미래전기차수"] / df["인구비율로본미래충전소개수"]
plt.figure(figsize=(20,6))
sns.barplot(data=df, x=df.index, y="미래충전소당전기차예측(인구기준)", ci=None).set_title("미래충전소당전기차예측(인구기준)")

folium 지도시각화

# 서울 행정구역 json raw파일(githubcontent)
r = requests.get('https://raw.githubusercontent.com/southkorea/seoul-maps/master/kostat/2013/json/seoul_municipalities_geo_simple.json')
c = r.content
seoul_geo = json.loads(c)

# 위도
lat = 37.394946
# 경도
lon = 127.111104

서울시 전기차 시각화

# 서울시 전기차 대수
m1 = folium.Map(
    location=[lat, lon],
    zoom_start=11, 
    tiles='cartodbpositron'
)

folium.GeoJson(
    seoul_geo,
    name='지역구'
).add_to(m1)

m1.choropleth(geo_data=seoul_geo,
             data=df['전기차수'], 
             fill_color='YlGnBu', # 색상 변경도 가능하다
             fill_opacity=0.5,
             line_opacity=0.2,
             key_on='properties.name',
             legend_name="행정동별 전기차 수"
            )
m1

서울시 충전소 시각화

m2 = folium.Map(
    location=[lat, lon],
    zoom_start=11, 
    tiles='cartodbpositron'
)

folium.GeoJson(
    seoul_geo,
    name='지역구'
).add_to(m2)

m2.choropleth(geo_data=seoul_geo,
             data=df['충전소'], 
             fill_color='YlGnBu', # 색상 변경도 가능하다
             fill_opacity=0.5,
             line_opacity=0.2,
             key_on='properties.name',
             legend_name="행정동별 충전소 개수"
            )
m2

결론

현재 자동차당 주유소 비율 기준으로 충전소는 늘리는 것이 인구비율로 충전소를 늘리는 것 보다

충전소당 감당해야 하는 전기차 수의 표준편차를 줄이는데 더 효과적인다.

사용한 데이터셋

https://data.seoul.go.kr/dataList/OA-21245/F/1/datasetView.do

https://www.data.go.kr/data/15098386/fileData.do

https://kosis.kr/statHtml/statHtml.do?orgId=101&tblId=DT_1IN1502&vw_cd=MT_ZTITLE&list_id=A11_2015_1_10_10&scrId=&seqNo=&lang_mode=ko&obj_var_id=&itm_id=&conn_path=MT_ZTITLE&path=%252FstatisticsList%252FstatisticsListIndex.do

https://www.ev.or.kr/evmonitor

https://data.seoul.go.kr/dataList/OA-21279/S/1/datasetView.do

profile
Ⓓ🅰️🅣🄰 ♡♥︎

0개의 댓글