코딩
Plotly 사용법 튜토리얼_1. 막대그래프 (Bar Chart)
그리즐리_곰
2023. 9. 27. 17:48
파이썬의 대표적인 그래프 라이브러리인 plotly를 활용하여 막대그래프를 그리는 방법을 소개합니다.
데이터셋은 행정안전부 홈페이지를 통해 다운받을 수 있는 주민등록 인구 현황 데이터를 사용하겠습니다.
https://jumin.mois.go.kr/index.jsp
※ 행정안전부 → 정책자료 → 주민등록 인구통계 → 주민등록 인구 및 세대현황 → 조회기간: 연간 (2016.12 ~ 2022.12) → 검색 클릭 → csv파일 다운로드
201612_202212_주민등록인구및세대현황_연간.csv
0.01MB
pandas로 전처리하는 과정은 생략하고 위 파일을 사용하여 튜토리얼을 진행하겠습니다.
1. 기본 막대그래프 만들기
import pandas as pd
df = pd.read_csv("201612_202212_주민등록인구및세대현황_연간.csv", encoding='cp949')
df = df[df['연도']==2022]
# 22년 데이터로 먼저 그래프를 그려봅니다.
import plotly.graph_objects as go
fig = go.Figure()
# Figure 인스턴스를 생성하고 뒤에오는 add_trace 함수로 데이터를 추가해줍니다.
fig.add_trace(go.Bar(x = df['행정구역'],
y = df['총인구수'],
)
)
# x축은 행정구역 (서울, 대전, 대구, 부산 등)
# y축은 구역별 인구수가 됩니다.
html = fig.to_html()
with open('주민등록인구및세대현황_v1.html', "w", encoding="utf-8") as f:
f.write(html)
# fig.write_html("파일명.html")로 내보낼수도 있지만 인코딩오류로 한글이 깨질 수 있습니다.
[주민등록인구및세대현황_v1.html]
2. 차트 디자인 추가하기
fig = go.Figure()
fig.add_trace(go.Bar(x = df['행정구역'],
y = df['총인구수'].apply(lambda x: round(x/10000,1)),
# 만단위로 표현해주기 위해 10000으로 나눠줍니다.
marker_color = '#4472C4',
# 막대 색상을 설정합니다.
text = df['총인구수'].apply(lambda x: f"{round(x/10000,1):,} 만"),
# text는 데이터 레이블 값입니다.
textposition="inside",
# 레이블을 막대안에 위치시킵니다.
# 'inside', 'outside', 'auto', 'none' 값을 줄 수 있습니다.
textfont=dict(family="맑은 고딕",
size=10,
color="#fff"
),
# 데이터 레이블의 폰트, 사이즈, 색상을 정의합니다.
hovertext = df['행정구역'] + " : " + df['총인구수'].apply(lambda x: f"{round(x/10000,1):,} 만"),
# hovertext는 마우스를 막대에 가져다 댔을 때 표시할 텍스트를 의미합니다.
hoverinfo = 'text'
)
)
fig.update_layout(paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
# 차트배경과 전체 배경을 투명하게 설정합니다.
# 원하는 색을 rgb 또는 헥스코드로 입력할 수 있습니다.
yaxis = dict(linecolor = '#888888',
# 좌측 y축 선의 색상을 정의합니다.
showgrid = True,
# 보조축을 보여줄지 설정합니다.
gridwidth = 1,
# 보조축의 굵기를 설정합니다.
gridcolor = '#aaaaaa',
# 보조축의 라인색상을 정의합니다.
griddash = 'dot',
# 보조축의 타입을 점선으로 설정합니다.
dtick = 200,
# y축 단위를 설정합니다.
ticksuffix="<br>(단위: 백만)",
showticksuffix="last",
# y축 맨위에 단위 정보를 표시하기 위해 설정합니다.
separatethousands= True
# 숫자에 콤마를 추가해줍니다.
),
xaxis = dict(linecolor = '#888888'),
font = dict(family = '맑은 고딕',
size = 12)
)
html = fig.to_html()
with open('주민등록인구및세대현황_v2.html', "w", encoding="utf-8") as f:
f.write(html)
[주민등록인구및세대현황_v2.html]
3. 연도별 막대그래프 만들기
df = pd.read_csv("201612_202212_주민등록인구및세대현황_연간.csv", encoding='cp949')
# 이번에는 데이터를 2022년으로 제한하지 않고 모두 가져옵니다.
fig = go.Figure()
colors = {2016:'#808080',
2017:'#404040',
2018:'#4472C4',
2019:'#548235',
2020:'#A9D08E',
2021:'#F4B084',
2022:'#C65911'}
# dictionary로 연도별 막대에 사용할 색상을 정의해줍니다.
for x in range(2016,2023):
temp = df[df['연도']==x].copy()
fig.add_trace(go.Bar(x = temp['행정구역'],
y = temp['총인구수'].apply(lambda x: round(x/10000,1)),
marker_color = colors[x],
text = temp['총인구수'].apply(lambda x: f"{round(x/10000,1):,} 만"),
textposition="inside",
hovertext = temp['행정구역'] + " : " + temp['총인구수'].apply(lambda x: f"{round(x/10000,1):,} 만"),
hoverinfo = 'text',
name = f"{x}년"
)
)
# 동일한 fig에 연도별 데이터를 반복하여 추가해줍니다.
# 한 그래프에 여러개의 막대가 생성되게 할 수 있습니다.
fig.update_layout(paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
yaxis = dict(linecolor = '#888888',
showgrid = True,
gridwidth = 1,
gridcolor = '#aaaaaa',
griddash = 'dot',
dtick = 200,
ticksuffix="<br>(단위: 백만)",
showticksuffix="last",
separatethousands= True
),
xaxis = dict(linecolor = '#888888'),
font = dict(family = '맑은 고딕',
size = 12),
)
# 차트에서 범례를 클릭하면 특정연도를 선택하거나 해제할 수 있는데
# 아래 코드는 모든 연도를 선택하거나 해제해주는 버튼을 추가하는 코드입니다.
fig.update_layout(dict(updatemenus=[dict(type = "buttons",
direction = "left",
buttons=list([dict(args=["visible", "legendonly"],
label="전체해제",
method="restyle"
),
dict(args=["visible", True],
label="전체선택",
method="restyle"
)
]
),
pad={"r": 10, "t": 10},
showactive=False,
x=1,
xanchor="right",
y=1.1,
yanchor="top"
),
]
)
)
html = fig.to_html()
with open('202308_주민등록인구및세대현황_v3.html', "w", encoding="utf-8") as f:
f.write(html)
[주민등록인구및세대현황_v3.html]
또는 연도별 그래프를 각기 다른 파일로 생성하고 Layout.html 파일에서 드롭다운 메뉴로 선택하여 특정 연도를 보여주게 할 수 있습니다.
[Layout.html]
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src=http://code.jquery.com/jquery.js>
</script>
<script type="text/javascript">
function updatedata() {
var selected_data = document.getElementById("year").value;
document.getElementById("imported").setAttribute('data', selected_data);
}
</script>
</head>
<style>
body {
margin : auto;
width : 80%;
max-width: 800px;
}
.wrapper {
margin : 0;
width :100%;
display: flex;
align-items:baseline;
}
.title {
text-align: left;
padding: 10px;
float:left;
font-family: '맑은 고딕';
font-weight: bold;
border-left: 3px solid #C00000;
}
.dropdownmenu {
margin-left: auto;
}
.chart {
padding: 10px 0;
font-family: '맑은 고딕';
height: 500px;
display: flex;
}
select {
background-color: #ED7D31;
border:5px;
width:80px;
color:white;
text-shadow: 0 0 0 white;
}
object {
width : 100%;
height : 100%;
}
</style>
<body>
<div class = 'wrapper'>
<div class = 'title'>연도별 주민등록인구 및 세대현황
</div>
<div class = 'dropdownmenu' style='display: inline'>
<select id = 'year' onchange="updatedata()">
<option value = 주민등록인구및세대현황_2022년.html>2022년</option>
<option value = 주민등록인구및세대현황_2021년.html>2021년</option>
<option value = 주민등록인구및세대현황_2020년.html>2020년</option>
<option value = 주민등록인구및세대현황_2019년.html>2019년</option>
<option value = 주민등록인구및세대현황_2018년.html>2018년</option>
<option value = 주민등록인구및세대현황_2017년.html>2017년</option>
<option value = 주민등록인구및세대현황_2016년.html>2016년</option>
</select>
</div>
</div>
<hr>
<div class = 'chart' id='chart'>
<object id='imported' type="text/html" data="주민등록인구및세대현황_2022년.html"></object>
</div>
</body>
</html>