Streamlit은 데이터사이언스/ML 프로젝트를 간단하게 배포할 수 있는 웹어플리케이션으로, 최근에 많은 관심을 받고 있습니다. 이번 포스트에서는 Streamlit의 간단한 소개와 기본 기능들을 훑어보겠습니다.


2020-03-13-intro-to-streamlit/streamlit_logo.png “Source: streamlit.io”)

Source: streamlit.io

Streamlit 이란?

Streamlit(스트림릿)은 2019년 하반기에 갑작스레 등장한(?) 파이썬 기반의 웹어플리케이션 툴이다. Medium 플랫폼에서 Streamlit이라는 키워드가 보이는 글이 추천되는 것을 자주 보게 되었는데, “데이터사이언스/머신러닝 프로젝트를 웹 어플리케이션에 배포"하는데 아주 편리한 툴이라는 설명이 눈길을 사로 잡았다.

 

나에게 있어 StreamlitDash 같은 웹어플리케이션의 장점을 꼽자면;

웹개발을 몰라도 된다.

  • 웹개발에 대해 아는 것이 전혀 없는 나 같은 사람도 페이지를 띄울 수 있다.
  • 주로 사내용으로 이용되기 때문에 UI/UX적인 측면에서 뛰어나지 않아도 되기 때문에 일정 수준의 미적인 요소들이 기본적으로 적용되있는 점이 매우 편리하다.
  • 간결하고 명확한 API 덕분에 다른 웹프레임워크와 비교해서 상대적으로 진입장벽이 낮다. 일정한 수준의 결과를 내기 위해 투자하는 시간이 매우 절약된다.

전달력이 매우 좋다.

  • 웹어플리케이션은 사용자에게도 진입장벽이 낮다. 특히 interactive한 성향 덕분에, 슬라이드 포맷의 레포트나 자료보다 전달력과 만족도가 높은 것을 볼 수 있었다.

 

덕분에 Streamlit은 조직 내부적으로 탐색적 데이터 분석(EDA) 결과를 공유하거나, 간단한 ML 모델을 배포하고 테스트를 하는 용도에 부합하는 툴이라고 할 수 있다. Streamlit API에서 제공하는 기능들을 간단하게 훑어보자.


Streamlit 간단 맛 보기

설치

pip를 통해 설치하기

$ pip install streamlit

 

실행하기

Streamlit8501 포트에 앱이 실행된다. 일단 지금 아무 것도 없는 상황에서는 우측 상단 버튼만 있는 페이지를 볼 수 있다.

$ streamlit run {your app}.py
You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://{your_network}:8501

Streamlit 불러오기

Streamlitst라는 alias로 불러온다.

# import Streamlit Library
import streamlit as st

소스에 변경이 생길 경우 경우 상단에 알림이 뜬다. Rerun을 해주도록 하자.

 

텍스트 출력

Header와 Text

  • Title, Header & Subheader
    • Header와 Subheader를 다음과 같이 달 수 있다. 다만 Header의 경우 subheader 레벨까지만 가능하다. Title, Header, Subheader이 각각 Header, Subheader, Subsubheader인 것으로 인식하면 될 것 같다.
## Title
st.title('Streamlit Tutorial')

## Header/Subheader
st.header('This is header')
st.subheader('This is subheader')

## Text
st.text("Hello Streamlit! 이 글은 튜토리얼 입니다.")

 

Markdown

StreamlitDash와 마찬가지로 Markdown을 지원한다.

## Markdown syntax
st.markdown("# This is a Markdown title")
st.markdown("## This is a Markdown header")
st.markdown("### This is a Markdown subheader")
st.markdown("- item 1\n"
            "   - item 1.1\n"
            "   - item 1.2\n"
            "- item 2\n"
            "- item 3")
st.markdown("1. item 1\n"
            "   1. item 1.1\n"
            "   2. item 1.2\n"
            "2. item 2\n"
            "3. item 3")

2020-03-13-intro-to-streamlit/4

 

Latex

Latex의 경우 백슬래시(\)를 빈번히 사용되기 때문에, 일반 string 대신 raw string을 붙여주는 편이 좋다.

## Latex
st.latex(r"Y = \alpha + \beta X_i")

## Latex-inline
st.markdown(r"회귀분석에서 잔차식은 다음과 같습니다 $e_i = y_i - \hat{y}_i$")

 

메세지와 에러메세지, 예외처리 메세지

기본적으로 포맷된 메세지 박스 기능을 제공한다.

## Error/message text
st.success("Successful")
st.info("Information!")
st.warning("This is a warning")
st.error("This is an error!")
st.exception("NameError('Error name is not defined')")

   

데이터프레임과 테이블 출력.

데이터를 출력하는 방법에는 3가지 방법이 있다.

  • st.table:

    • 단순히 입력 테이블 전체를 리턴한다.
  • st.dataframe:

    • 적절히 10개의 행을 기준으로 스크롤을 통해 데이터를 관찰 할 수 있고 각 열마다 정렬도 가능하다. 각 테이블의 우측 상단의 확대 버튼을 통해 테이블을 더 크게 볼 수 있고,
  • st.write:

    • st.dataframe과 똑같은 결과를 리턴한다.
## Load data
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
iris_df['target'] = iris['target']
iris_df['target'] = iris_df['target'].apply(lambda x: 'setosa' if x == 0 else ('versicolor' if x == 1 else 'virginica'))

## Return table/dataframe
# table
st.table(iris_df.head())

# dataframe
st.dataframe(iris_df)
st.write(iris_df)

   

이미지, 오디오, 비디오 파일 출력.

이미지, 영상, 오디오 파일을 열어서 재생할 수 있다.

  • st.image : 파이썬 이미지 라이브러리와 함께 쓸 수 있다.
  • st.video :
    • 파일의 포맷을 지정해야 하며, 디폴트로는 video/mp4가 설정되어 있다.
    • start_time 변수를 통해 재생시작점을 조절할 수 있다.
  • st.audio :
    • 파일 포맷은 audio/wav 가 디폴트로 설정되어 있다.
    • 마찬가지로 start_time 변수를 통해 재생시작점을 조절할 수 있다.
##Show image
from PIL import Image
img = Image.open("files/example_cat.jpeg")
st.image(img, width=400, caption="Image example: Cat")

## Show videos
vid_file = open("files/example_vid_cat.mp4", "rb").read()
st.video(vid_file, start_time=2)

## Play audio file.
audio_file = open("files/loop_w_bass.mp3", "rb").read()
st.audio(audio_file, format='audio/mp3', start_time=10)

   

위젯

st.checkbox - 체크박스

## Checkbox
if st.checkbox("Show/Hide"):
    st.write("체크박스가 선택되었습니다.")

 

st.radio - 라디오버튼

## Radio button
status = st.radio("Select status.", ("Active", "Inactive"))
if status == "Active":
    st.success("활성화 되었습니다.")
else:
    st.warning("비활성화 되었습니다.")

 

st.selectbox - 드랍다운 선택

## Select Box
occupation = st.selectbox("직군을 선택하세요.",
                          ["Backend Developer",
                           "Frontend Developer",
                           "ML Engineer",
                           "Data Engineer",
                           "Database Administrator",
                           "Data Scientist",
                           "Data Analyst",
                           "Security Engineer"])
st.write("당신의 직군은 ", occupation, " 입니다.")

 

st.multiselect - 드랍다운 다중 선택

## MultiSelect
location = st.multiselect("선호하는 유투브 채널을 선택하세요.",
                          ("운동", "IT기기", "브이로그",
                           "먹방", "반려동물", "맛집 리뷰"))
st.write(len(location), "가지를 선택했습니다.")

 

st.slider - 슬라이더

## Slider
level = st.slider("레벨을 선택하세요.", 1, 5)

 

st.button - 버튼

## Buttons
if st.button("About"):
    st.text("Streamlit을 이용한 튜토리얼입니다.")

 

텍스트 입력

# Text Input
first_name = st.text_input("Enter Your First Name", "Type Here ...")
if st.button("Submit", key='first_name'):
    result = first_name.title()
    st.success(result)


# Text Area
message = st.text_area("메세지를 입력하세요.", "Type Here ...")
if st.button("Submit", key='message'):
    result = message.title()
    st.success(result)

 

날짜와 시간 입력

## Date Input
import datetime
today = st.date_input("날짜를 선택하세요.", datetime.datetime.now())
the_time = st.time_input("시간을 입력하세요.", datetime.time())

 

코드와 JSON 출력

  • with st.echo(): 이하의 코드는 코드블럭으로 출력된다.
## Display Raw Code - one line
st.subheader("Display one-line code")
st.code("import numpy as np")

# Display Raw Code - snippet
st.subheader("Display code snippet")
with st.echo():
    # 여기서부터 아래의 코드를 출력합니다.
    import pandas as pd
    df = pd.DataFrame()

## Display JSON
st.subheader("Display JSON")
st.json({'name' : '민수', 'gender':'male', 'Age': 29})

 

사이드바

st.sidebar에서도 대부분의 위젯을 지원하므로, 다양하게 사이드바를 구성할 수 있다. (단, st.echo, st.spinner, st.write제외)

## Sidebars
st.sidebar.header("사이드바 메뉴")
st.sidebar.selectbox("메뉴를 선택하세요.", ["데이터", "EDA", "코드"])

 

차트 그리기

Streamlit은 자체 내장된 기본적인 차트 외 matplotlib, plot.ly, altair, vega_ilte, bokeh, deck_gl, pydeck, graph_viz 등 다양한 시각화 패키지를 지원한다.

(Streamlit은 EDA 용도로 많이 사용되는 만큼, 시각화 부분은 따로 다룰 계획이다.)

## Plotting
st.subheader("Matplotlib으로 차트 그리기")
iris_df[iris_df['target']=='virginica']['petal length (cm)'].hist()
st.pyplot()

   


마무리

Streamlit의 API를 훑어보면서, 전체적으로 많은 부분이 간결하고, 쉽다고 느껴졌다. Flask나 Django로 개발하는 개발자 입장에서 Streamlit 같은 프레임워크는 자유도가 제한된다고 느껴질 수도 있겠다. 하지만 등장한지 얼마 안 되는 만큼 커뮤니티 포럼에서는 활발한 토론과 기능 추가에 대한 요청이 이어지고 있는 중이다. Streamlit 개발자들이 적극적으로 피드백을 반영하는 모습을 보이고 있으므로, 앞으로의 발전이 더 기대된다.

이번 소개 글에 이어, 개인적으로 Streamlit으로 개발하면서 얻은 팁이나, 클라우드 또는 Heroku에 배포하는 과정, 데이터사이언스 프로젝트를 위해 웹어플리케이션을 구성하는 팁 등을 시리즈로 작성할 예정이다. 나처럼 웹개발은 모르지만 데이터분석 결과를 그럴 듯하게 구성하고 싶은 분들께 도움이 되었으면 한다.

 

코드

 

참고자료