본문 바로가기
Programming/Python

Streamlit - Kaggle DALYs 데이터 분석 & 시각화 - 1

by BTC_박현영 2023. 8. 16.

베하~ 안녕하세요! BTC_현상수배범 입니다.

오늘은 지난 시간에 배웠던 Streamlit을 활용하여, DALYs 데이터에 대해 Boxplot을 그려보고자 합니다.

분석에 사용할 데이터는 <링크> 에서 다운로드할 수 있고, 1990년 ~ 2019년 까지의 데이터가 있습니다.

해당 데이터는 여러 질병, 재해에 대한 DALY 수치가 저장된 데이터프레임입니다.

 

DALYs란?

DALYs(Disability-adjusted life years)는 사람들이 얼마나 오래 건강하게 살았는지에 대해 나타내는 지표입니다. DALYs는 주요한 두 가지 지표(YLL, YLD)로 구성됩니다.

1. YLL(Years of Life Lost): 사람들이 질병, 건강 문제 등으로 인해 일찍 사망하여, 건강했을 때에 비해 잃은 연수(n년)을 의미합니다. 

2. YLD(Years Lost due to Disability): 사람들이 질병, 건강 문제 등으로 인해 건강하지 않은 상태로 보낸 연수(n년)을 의미합니다.

예시로, 어떠한 질병으로 인해 A라는 사람이 5년 일찍 사망했고, 사망 이전에 10년 동안 해당 질병으로 인해 건강하지 않게 생활했다면, 해당 질병의 DALYs는 15년 입니다.

즉, DALYs는 해당 질병, 상황으로 인해 잃어버린 건강하게 지낼 수 있었던 연수를 의미합니다.

 

1. 데이터 확인 & 불필요한 데이터 삭제

먼저 데이터를 살펴보시면, Entity, Code, Year 컬럼을 제외하고는 전부 질병 및 재해에 대한 컬럼을 가지고 있음을 확인할 수 있습니다. 불필요한 데이터인 1번째 컬럼은 drop()으로 제거했습니다.

import streamlit as st
import pandas as pd

def file_upload():
    return st.sidebar.file_uploader('Choose a file', type=['csv'], accept_multiple_files=False)

def main():
    st.set_page_config(layout="wide")

    raw_data = file_upload()
    
    if raw_data != None:
        raw_data = pd.read_csv(raw_data)
        raw_data = raw_data.drop(columns=['Unnamed: 0'])
        st.write("raw_data", raw_data)
    else:
        st.warning("Please upload a csv file")

if __name__ == "__main__":
    main()

 

2. 데이터 필터링

저의 경우에는 우리나라와 북한, 일부 대륙의 DALYs 수치가 궁금했기 때문에, 모든 국가,대륙 별 DALY 수치를 확인할 필요는 없었습니다. 따라서 Streamlit의 multiselect를 활용하여 필터링을 해보았습니다. 컬럼 중, Entity(국가명), Code(국가 코드), Years(연도) 세 가지는 포함되어야 할 것이라고 생각되어 이 세 가지 컬럼은 포함되도록 하였습니다.

def preprocess_data(data, entity_option, DALY_option, exclude_columns):
    column_option = exclude_columns + DALY_option
    filtered_data = data[data['Entity'].isin(entity_option)][column_option]
    return filtered_data
    
    
def main():
    st.set_page_config(layout="wide")

    raw_data = file_upload()
    
    if raw_data != None:
        raw_data = pd.read_csv(raw_data)
        raw_data = raw_data.drop(columns=['Unnamed: 0'])
        st.write("raw_data", raw_data)
        
        raw_columns = raw_data.columns.tolist()
        exclude_columns = ['Entity', 'Code', 'Year']
        columns = [column for column in raw_columns if column not in exclude_columns]
        
        countries = raw_data['Entity'].unique().tolist()
        selected_entities = st.sidebar.multiselect(label='Select Entities',
                                                    options=countries,
                                                    key='selected_entities',
                                                    help='Please select Entities to analyze. If nothing is selected, it is considered as selecting all.') or countries
        selected_DALY = st.sidebar.multiselect(label='Select DALY options',
                                                  options=columns,
                                                  key='selected_DALY',
                                                  help='Please select options to perform DALY analysis. If nothing is selected, it is considered as selecting all. "Entity", "Code", "Year" Columns are always included') or columns
        if st.sidebar.button('submit'):
            data = preprocess_data(raw_data, selected_entities, selected_DALY, exclude_columns)
            st.write("selected_entities: ", data['Entity'].unique().tolist())
            st.write("selected_DALY", data.columns)
        
    else:
        st.warning("Please upload a csv file")

multiselect를 통해 보고 싶은 Entity, DALYs에 대해 선택하고 submit 버튼을 클릭하면, 우측에 보시는 것 처럼 선택한 값들만 제대로 필터링되어 나오는 것을 확인할 수 있습니다.

 

 

3. Boxplot

현재 Streamlit만 사용하여 Boxplot을 그릴 수는 없습니다. 다만, matplotlib이나 altair 등과 같은 라이브러리와의 통합을 지원하기 때문에 이를 활용하여 boxplot을 나타낼 수 있습니다. 저는 파이썬의 시각화 도구중 하나인 altair 라이브러리를 활용하여 그래프를 그려보도록 하겠습니다.

def get_boxplot_chart(data, entity_option, DALY_option):
    import altair as alt
    tabs = st.tabs(DALY_option)
    for i in range(len(DALY_option)):
        chart = alt.Chart(data).mark_boxplot(extent='min-max').encode(
            x='Entity:N',
            y=f'{DALY_option[i]}:Q',
            color='Entity:N'
        )
        with tabs[i]:
            st.altair_chart(chart, theme="streamlit", use_container_width=True)
            
def main():
    st.set_page_config(layout="wide")

    raw_data = file_upload()
    
    if raw_data != None:
        raw_data = pd.read_csv(raw_data)
        raw_data = raw_data.drop(columns=['Unnamed: 0'])
        
        raw_columns = raw_data.columns.tolist()
        exclude_columns = ['Entity', 'Code', 'Year']
        columns = [column for column in raw_columns if column not in exclude_columns]
        
        countries = raw_data['Entity'].unique().tolist()
        selected_entities = st.sidebar.multiselect(label='Select Entities',
                                                    options=countries,
                                                    key='selected_entities',
                                                    help='Please select Entities to analyze. If nothing is selected, it is considered as selecting all.') or countries
        selected_DALY = st.sidebar.multiselect(label='Select DALY options',
                                                  options=columns,
                                                  key='selected_DALY',
                                                  help='Please select options to perform DALY analysis. If nothing is selected, it is considered as selecting all. "Entity", "Code", "Year" Columns are always included') or columns
        if st.sidebar.button('submit'):
            data = preprocess_data(raw_data, selected_entities, selected_DALY, exclude_columns)
            get_boxplot_chart(data, selected_DALY)
        
    else:
        st.warning("Please upload a csv file")

 

3.1 Boxplot - Nutritional deficiencies(영양 결핍)

X축은 각 국가/대륙을 나타내며, Y 축이 특정 질병/재해로 인한 DALYs 수치입니다.

첫 번째 그래프는 Nutritional deficiencies(영양 결핍)으로 인한 DALYs 수치로, 북한의 수치가 가장 높게 나타나는 것을 확인할 수 있습니다. 가끔 탈북민들께서 출연하시는 유튜브 영상을 보다 보면, 북한에 있을 때는 하루하루 뭘 먹고 살아야 할지 걱정했었다고 하시는 분들을 자주 봤었는데 정말 힘드셨을 것 같습니다. Max 값이 31.9769...로 심한 연도에는 약 31~32년을 건강하지 못하게 생활했었다고 볼 수 있습니다. 31이라는 수치가 나오는 것이 궁금해서 확인해 보았습니다.

위 데이터를 보시면, 1995년부터 2000년대 초반까지 Nutritional deficiencies 수치가 매우 높습니다. 구글링해보니, 저 때가 대기근이 발생했었던 고난의 행군 때였습니다. 최소 약 100만 명에서 최대 약 300만 명이 아사했다고 추정된다고 하니, 수치가 높은 것이 이해가 됩니다.

 

3.2 Boxplot - Self harm(자해)

이번에는 자해로 인한 DALYs 수치를 확인해보았습니다. 우리나라의 수치가 가장 높게 나타나는 것을 확인할 수 있는데, OECD 국가 중 자살률이 가장 높은 나라임을 감안해보면 그리 이상한 수치는 아닌 것 같습니다. 연령, 성별과 같은 정보가 담겨있지 않아 어떤 유형의 사람들이 가장 많이 자해를 했는지를 알 수 없어서 원인 유추가 어려웠습니다. 다음에는 각 질병/재해 간 상관 분석 & 지도에 시각화를 해보고자 합니다.

댓글