Today I Learned (TIL)/Python

[TIL] Python 챌린지 - 6회차

신짜린 2024. 8. 8. 12:58

1. Streamlit 소개

Streamlit은 데이터 과학자와 머신러닝 엔지니어를 위한 오픈소스 Python 라이브러리이다. 복잡한 데이터 애플리케이션을 빠르고 쉽게 만들 수 있도록 설계되었으며 단순한 Pyhon 스크립트 만으로도 대화형 웹 애플리케이션을 만들 수 있다.

 

2. Streamlit 설치 및 기본 구조

pip install streamlit
import streamlit as st

def main():
    st.title("My Streamlit App")
    # 앱의 내용을 여기에 추가합니다

if __name__ == "__main__":
    main()

 

3. Streamlit 주요 UI 요소

- 텍스트 출력

import streamlit as st

st.title("Streamlit 텍스트 출력 예제")

st.header("1. 텍스트 출력")
st.subheader("다양한 텍스트 출력 방법")

st.text("이것은 일반 텍스트입니다.")
st.markdown("**이것은 마크다운 텍스트입니다.**")

 

- 입력 위젯

st.header("2. 입력 위젯")

# 텍스트 입력
name = st.text_input("이름을 입력하세요")
st.write(f"입력된 이름: {name}")

# 숫자 입력
age = st.number_input("나이를 입력하세요", min_value=0, max_value=120, value=30)
st.write(f"입력된 나이: {age}")

# 체크박스
is_happy = st.checkbox("행복하신가요?")
st.write(f"행복 여부: {is_happy}")

# 슬라이더
happiness_level = st.slider("행복 지수", 0, 100, 50)
st.write(f"행복 지수: {happiness_level}")

 

- 선택 위젯

st.header("3. 선택 위젯")

# 단일 선택
favorite_color = st.selectbox("좋아하는 색깔을 선택하세요", ["빨강", "파랑", "초록", "노랑"])
st.write(f"선택한 색깔: {favorite_color}")

# 다중 선택
favorite_fruits = st.multiselect("좋아하는 과일을 모두 선택하세요", ["사과", "바나나", "체리", "두리안"])
st.write(f"선택한 과일: {favorite_fruits}")

 

- 버튼

st.header("4. 버튼")

if st.button("클릭하세요"):
    st.write("버튼이 클릭되었습니다!")

 

- 사이드바

st.sidebar.header("5. 사이드바")

sidebar_slider = st.sidebar.slider("사이드바 슬라이더", 0, 100, 50)
st.sidebar.write(f"사이드바 슬라이더 값: {sidebar_slider}")

 

- 컬럼 레이아웃

st.header("6. 컬럼 레이아웃")

col1, col2 = st.columns(2)

with col1:
    st.write("이것은 첫 번째 컬럼입니다.")
    st.image("https://streamlit.io/images/brand/streamlit-mark-color.png", width=200)

with col2:
    st.write("이것은 두 번째 컬럼입니다.")
    st.image("https://streamlit.io/images/brand/streamlit-mark-color.png", width=200)

 

- 데이터 표시

import pandas as pd
import numpy as np

st.header("7. 데이터 표시")

df = pd.DataFrame(
    np.random.randn(5, 3),
    columns=('Col 1', 'Col 2', 'Col 3')
)

st.subheader("DataFrame 표시")
st.dataframe(df)

st.subheader("정적 테이블 표시")
st.table(df)

 

- 차트

import matplotlib.pyplot as plt

st.header("8. 차트")

st.subheader("Matplotlib 차트")
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4], [1, 4, 2, 3])
st.pyplot(fig)

 

- 파일 업로더

st.header("9. 파일 업로더")

uploaded_file = st.file_uploader("파일을 선택하세요", type=["csv", "txt"])
if uploaded_file is not None:
    st.write("파일이 업로드되었습니다!")
    st.write(f"파일명: {uploaded_file.name}")

 

4. 상태 관리

 Streamlit은 st.session_state를 통해 세션 상태를 관리할 수 있다.

st.header("10. 상태 관리")

if 'count' not in st.session_state:
    st.session_state.count = 0

if st.button("카운트 증가"):
    st.session_state.count += 1

st.write(f"현재 카운트: {st.session_state.count}")

 

5. 캐싱

@st.cache_data 데코레이터를 사용하여 함수의 결과를 캐시할 수 있다.

st.header("11. 캐싱")

@st.cache_data
def expensive_computation(a, b):
    # 시간이 오래 걸리는 연산을 시뮬레이션
    import time
    time.sleep(2)
    return a * b

result = expensive_computation(10, 20)
st.write(f"계산 결과: {result}")

 

6. 손으로 해보는 코딩

import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import time

# 페이지 설정
st.set_page_config(layout="wide", page_title="데이터 대시보드")

# 캐시를 사용한 데이터 로딩
@st.cache_data
def load_data():
    # 실제로는 여기서 데이터를 로드하거나 API를 호출할 수 있습니다
    df = pd.DataFrame(
        np.random.randn(1000, 5),
        columns=['A', 'B', 'C', 'D', 'E']
    )
    return df

# 캐시를 사용한 계산 집약적 함수
@st.cache_data
def perform_expensive_calculation(df):
    time.sleep(2)  # 계산에 시간이 걸리는 것을 시뮬레이션
    return df.corr()

# 메인 함수
def main():
    st.title("인터랙티브 데이터 대시보드")

    # 데이터 로딩
    df = load_data()

    # 사이드바
    st.sidebar.header("설정")
    selected_columns = st.sidebar.multiselect(
        "분석할 열을 선택하세요",
        options=df.columns.tolist(),  # 리스트로 변환
        default=df.columns[:2].tolist()  # 리스트로 변환
    )

    # 선택된 열이 없으면 모든 열을 선택
    if not selected_columns:
        selected_columns = df.columns.tolist()

    # 메인 영역
    col1, col2 = st.columns(2)

    with col1:
        st.subheader("데이터 미리보기")
        st.dataframe(df[selected_columns].head())

        st.subheader("기술 통계")
        st.write(df[selected_columns].describe())

    with col2:
        st.subheader("상관 관계")
        if st.button("상관 관계 계산"):
            with st.spinner("계산 중..."):
                corr = perform_expensive_calculation(df[selected_columns])
            st.write(corr)

            # 히트맵
            fig, ax = plt.subplots()
            sns.heatmap(corr, annot=True, cmap='coolwarm', ax=ax)
            st.pyplot(fig)

    # 그래프 영역
    st.header("데이터 시각화")

    # 선 그래프
    st.subheader("선 그래프")
    fig, ax = plt.subplots()
    for column in selected_columns:
        ax.plot(df.index, df[column], label=column)
    ax.legend()
    ax.set_xlabel("Index")
    ax.set_ylabel("Value")
    st.pyplot(fig)

    # 산점도
    st.subheader("산점도")
    if len(selected_columns) >= 2:
        x_axis = st.selectbox("X 축 선택", selected_columns)
        y_axis = st.selectbox("Y 축 선택", [col for col in selected_columns if col != x_axis])
        fig, ax = plt.subplots()
        ax.scatter(df[x_axis], df[y_axis])
        ax.set_xlabel(x_axis)
        ax.set_ylabel(y_axis)
        st.pyplot(fig)
    else:
        st.write("산점도를 그리려면 최소 2개의 열을 선택해주세요.")

    # 히스토그램
    st.subheader("히스토그램")
    column_for_hist = st.selectbox("히스토그램을 그릴 열 선택", selected_columns)
    fig, ax = plt.subplots()
    ax.hist(df[column_for_hist], bins=30)
    ax.set_xlabel(column_for_hist)
    ax.set_ylabel("Frequency")
    st.pyplot(fig)

    # 인터랙티브 요소
    st.header("인터랙티브 필터링")
    min_value = st.slider("최소값 필터", float(df[selected_columns].min().min()), float(df[selected_columns].max().max()))
    filtered_df = df[df[selected_columns] > min_value]
    st.write(f"{len(filtered_df)} 개의 행이 선택되었습니다.")
    st.dataframe(filtered_df)

if __name__ == "__main__":
    main()