본문 바로가기

코딩

Plotly 사용법 튜토리얼_1. 막대그래프 (Bar Chart)

파이썬의 대표적인 그래프 라이브러리인 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>