Search

Streamlit

특징

빠름 (파이썬 기반 언어)
Web Application 기반
웹개
공유 가능
유저와 상호 작용에 좋음(동적 기반)
대시보드 만들기에 좋음
주로 프로토타입 만들 때 사용
주로 ML / DL 관련 토이프로젝트
스트림릿으로 구현한 웹을 바로 product로 사용하기엔 다듬어야 할 부분이 많아 디테일한 조정등은 CSS hack 을 통해 조정한다.
다른 대안 : pyscript
단, 보완되어야 할 점이 정말 많다고 한다.

기본 element

import streamlit as st
Python
복사

Text element

title
st.title('This is title')
Python
복사
header
st.header('This is header')
Python
복사
subheader
st.subheader('This is subheader')
Python
복사
markdown
st.markdown('# Markdown 1st') st.markdown('## Markdown 2nd') st.markdown('### Markdown 3rd') st.markdown('**_Markdown 진하고 기울임_**') st.markdown(' - Markdown 글머리 기호')
Python
복사
divider : 구분선
st.divider()
Python
복사
caption : 설명, 각주
st.caption('caption - 설명, 각주, 작은 메모, 설명문')
Python
복사
code
웹페이지 상에서 코드 복붙이 가능한 형태로 나온다.
st.code('x=1234')
Python
복사
latex
st.latex(r'''a + ar + ar^2 + ar^3 ''')
Python
복사
write
거의 모든게 가능한 만능 함수
데이터프레임도 만들 수 있다.
st.title('write') st.write('this is a string write') st.write('Hello, _World!_ 🩵') st.caption('참고사이트: https://docs.streamlit.io/library/api-reference/write-magic/st.write') st.caption("{'이름': ['홍길동', '김사랑', '일지매', '이루리'],'수준': ['금', '동', '은', '은']}") df = pd.DataFrame({'이름': ['홍길동', '김사랑', '일지매', '이루리'],'수준': ['금', '동', '은', '은']}) st.write(df)
Python
복사

Media element

이미지, 오디오, 비디오를 삽입할 수 있다.
st.image('이미지 url / 파일') st.audio('오디오 url / 파일') st.video('비디오 url / 파일')
Python
복사

Data display elements

metric
박스 칸이라고 생각하면 편함.
st.title('Unit 3. Data display elements') st.caption('참조사이트: https://docs.streamlit.io/library/api-reference/data') st.header(' 1. Metric') st.metric(label='Temperature', value='24℃', delta='2.5℃')
Python
복사
metric + columns
st.header('2. Columns') col1, col2, col3 = st.columns(3) # 세 칸(열)을 형성 # col1, col2, col3 = st.columns([2, 1, 1]) -> 똑같이 3열을 생성하는데, 첫번째 열에서 2만큼의 자리를 생성 col1.metric('기온', '24℃', '2.5℃') col2.metric('풍속', '9 mph', '-8%') col3.metric('습도', '55%', '4%')
Python
복사
데이터프레임 조회, 수정
write() = dataframe() : 스크롤바 생성/ table() : 고정형태
data_editor() : 데이터 프레임 값 수정 가능
titanic = pd.read_csv('https://raw.githubusercontent.com/huhshin/streamlit/master/data_titanic.csv') st.markdown('- st.dataframe(상위 15행)') st.caption('dataframe, write- 10개 행 기준 스크롤, 열 크기조정, 열 정렬, 테이블 확대') st.dataframe(titanic.head(15)) st.markdown('- st.write(상위 15행)') st.write(titanic.head(15)) st.markdown('- st.table(상위 15행)') st.caption('table- 형태 고정') st.table(titanic.head(15)) st.markdown('- data_editor') edited_df = st.data_editor(titanic) # 데이터프레임에서 값을 수정할 수 있음 st.write(edited_df)
Python
복사

Input Widgets

button, slider, widget, input 등의 widget을 통해 상호작용을 가능하게 해줌
link button
링크 버튼을 생성 → 체크 → 링크 웹페이지로 이동
st.link_button('Widget Link', 'https://docs.streamlit.io/library/api-reference/widgets')
Python
복사
button
클릭 취소는 불가
클릭 유무에 따라 나타나는 내용을 변경할 수 있다
# Say hello 라는 버튼이 눌리면 -> Hello 아니면 Good bye if st.button('Say Hello'): st.write('Hello') else: st.write('Good bye')
Python
복사
radio button
여러 선택지 중 하나 선택
genre = st.radio('좋아하는 영화 장르를 선택해주세요!', ('코미디','SF/액션','로맨스')) if genre == '코미디': st.write('코미디! 유쾌하신 걸 좋아하시는 분이시군요!👌') elif genre == 'SF/액션': st.write('SF 액션! 저도 익사이팅한 영화를 좋아합니다 😉') else: st.write('영화 속 사랑이야기, 현실과는 다른 모습을 볼 수 있죠 (❁´◡`❁)')
Python
복사
checkbox : 체크 박스
체크 박스 체크 / 체크 해제에 따라 공간이 생기고 없어짐
agree = st.checkbox('I agree') if agree: st.write('Me too' + '💕' * 10)
Python
복사
toggle : 스위치
스위치를 on / off 하느냐에 따라 문구가 생기고 없어짐
on = st.toggle('Please click on this toggle!') if on: st.write('Feature activated! 💫')
Python
복사
selectbox : 여러 선택지 중 하나 선택
option = st.selectbox('어떻게 연락 드릴까요?',('Email', 'Mobile phone', 'Office phone')) st.write('네!', option, '으로 연락 드리겠습니다(●\'◡\'●)')
Python
복사
multiselect : 다중 선택
options = st.multiselect('좋아하는 색을 모두 선택해주세요', ['Green','Purple','Pink','Blue'], ['Green','Pink']) # 기본 선택값 st.write(', '.join(options), '색상을 좋아하시는군요!')
Python
복사

Input elements

text_input
텍스트 인풋
title = st.text_input('최애 영화를 입력하세요', 'After sun') # 기본값 st.write('당신이 가장 좋아하는 영화는 :', title)
Python
복사
number_input
수치 입력
number = st.number_input('Insert a number(1-10)', min_value=1, max_value=10, value=5, step=1) # value = 최초입력값, step = 증분값 st.write('The current number is ', number)
Python
복사
date_input
날짜 입력( 전후 10년까지의 선택지 선택 가능)
ymd = st.date_input('When is your birthday', datetime(2024,10,10)) # 입력값 전후 10년까지만 선택 가능 st.write('Your birthday is:', ymd)
Python
복사
chat_input
챗봇 기능처럼 프롬프트 입력 가능 → 출력됨
prompt = st.chat_input('Say something') # 프롬프트 기본값 if prompt: # 프롬프트에 값이 입력되면 st.write(f'User has sent the following prompt:{prompt}')
Python
복사

Slider elements

slider
# 밑 구간은 따로 조절 불가 age = st.slider('나이가 어떻게 되세요?',0,130,25) # 입력허용구간(0 ~ 130), 최초세팅값 25 st.write('I am', age, 'years old')
Python
복사
# 밑 구간, 윗 구간 모두 조절 가능 values = st.slider('값 구간을 선택하세요',0.0,100.0, (25.0,75.0)) st.write('Values: ', values)
Python
복사
날짜 구간 활용
slider_date = st.slider('날짜 구간을 선택하세요', min_value = datetime(2022,1,1), max_value = datetime(2022,12,31), value=(datetime(2022,6,1), datetime(2022,7,31)), # 초기 설정 구간 format='YY/MM/DD') st.write('slider date: ', slider_date) # 결과는 튜플 st.write('slider_date[0]:', slider_date[0], 'slider_date[1]:', slider_date[1])
Python
복사
날짜 구간으로 데이터 조회하기
df = pd.read_csv('data_subway_in_seoul.csv', encoding='cp949') st.write('날짜 필드 형식: ', df['날짜'].dtypes) st.write(df) # 데이터프레임 내용 확인하기
Python
복사
# 날짜 필드 string -> datetime 으로 변환 df['날짜'] = pd.to_datetime(df['날짜'], format='%Y-%m-%d') st.write('날짜 필드 형식:' , df['날짜'].dtypes) st.write(df)
Python
복사
slider_date = st.slider( '날짜 구간을 선택하세요.', datetime(2021,1,1), datetime(2021,12,31), value=(datetime(2021,7,1), datetime(2021,7,31)), format='YY/MM/DD') start_date = slider_date[0] end_date = slider_date[1] sel_df = df[df['날짜'].between(start_date, end_date)] st.write(sel_df)
Python
복사

Layouts & Containers

Sidebar 를 만들 수 있다.
sidebar + with 사용하기
with st.sidebar: st.header('1.Side bar')
Python
복사
add_selectbox = st.sidebar.selectbox( '어떻게 연락 드릴까요?', ('Email','Mobile Phone','Office Phone')) if add_selectbox == 'Email': st.sidebar.title('📧') elif add_selectbox == 'Mobile Phone': st.sidebar.title('📱') else: st.sidebar.title('☎︎')
Python
복사
Columns 와 Tab 을 이용해서 칸과 탭을 만들 수있다.
columns
col1, col2, col3 = st.columns(3) # with with col1: st.text('A cat') st.image('https://images.pexels.com/photos/2071873/pexels-photo-2071873.jpeg?auto=compress&cs=tinysrgb') with col2: st.text('A dog') st.image('https://images.pexels.com/photos/3361739/pexels-photo-3361739.jpeg?auto=compress&cs=tinysrgb') with col3: st.text('A owl') st.image('https://images.pexels.com/photos/3737300/pexels-photo-3737300.jpeg?auto=compress&cs=tinysrgb')
Python
복사
tabs
tab1, tab2, tab3 = st.tabs(['고양이','개','올빼미']) # with with tab1: st.text('Cat') st.image('https://images.pexels.com/photos/2071873/pexels-photo-2071873.jpeg?auto=compress&cs=tinysrgb', width=200) with tab2: st.text('Dog') st.image('https://images.pexels.com/photos/3361739/pexels-photo-3361739.jpeg?auto=compress&cs=tinysrgb', width=200) with tab3: st.text('Owl') st.image('https://images.pexels.com/photos/3737300/pexels-photo-3737300.jpeg?auto=compress&cs=tinysrgb', width=200)
Python
복사
다중 페이지 설정(메인 페이지, 서브 페이지 등)
# 페이지별 내용을 담은 함수 생성 def main_page(): st.title('Main page 🎈🎈') st.sidebar.title('Side Main 🎈') def page2(): st.title('Page 2 ❄️❄️') st.sidebar.title('Side 2❄️') def page3(): st.title('Page 3 🎉🎉') st.sidebar.title('Side 3 🎉')
Python
복사
# 딕셔너리 선언 {'selectbox 항목' : '페이지명' , ...} page_names_to_funcs = {'Main Page':main_page, 'Page 2':page2, 'Page 3':page3} # 사이드 바에서 selectbox 선언 & 선택 결과 저장 selected_page = st.sidebar.selectbox('Select a page', page_names_to_funcs.keys()) # 해당 페이지 부르기 page_names_to_funcs[selected_page]()
Python
복사

Data Handling

df = pd.read_csv('data_subway_in_seoul.csv', encoding='cp949') st.write(df) st.text("2. 구분이 '하차'인 행만 새로운 데이터프레임으로 저장 & 확인") df_off = df[df['구분']=='하차'] st.write(df_off) st.text("3. '날짜','연번','역번호','역명','구분','합계' 제외하고 저장 & 확인") df_line = df_off.drop(['날짜','연번','역번호','역명','구분','합계'], axis=1) st.write(df_line) st.text("4. 아래 방법으로 데이터프레임 변환하여 저장 & 확인") st.caption("melt 함수 사용 unpivot: identifier-'호선', unpivot column-'시간', value column-'인원수'") df_line_melted = pd.melt(df_line, id_vars=['호선'], var_name='시간', value_name='인원수') st.write(df_line_melted) st.text("5. '호선','시간' 별 '인원수' 합, as_index=False 저장 & 확인") df_line_groupby = df_line_melted.groupby(['호선','시간'], as_index=False)['인원수'].sum() st.write(df_line_groupby)
Python
복사

Chart elements

Streamlit은 다양한 형태의 chart를 위한 library를 제공하고 추가하고있습니다.
근간이 되는 라이브러리는 Matplotlib
chart_data = pd.read_csv('https://raw.githubusercontent.com/huhshin/streamlit/master/data_sales.csv')
Python
복사
Simple Line Chart
# use_container_width=True 가로로 화면에 꽉 채워 줌 st.line_chart(chart_data, use_container_width=True)
Python
복사
Simple Bar Chart
st.bar_chart(chart_data, use_container_width=True)
Python
복사
Simple Area Chart
st.area_chart(chart_data, use_container_width=True)
Python
복사
Altair Chart
파이썬을 기반으로 돌아가는 인터렉티브 시각화 패키지
선언형 방식 중 독특한 문법을 보여준다.
필수 요소
데이터, 마크, 인코딩, 인터렉티브(기본값 off)
데이터
마크
인코딩
인트렉티브
추가요소(옵션)
트랜스폼, 결합, 스케일과 가이드
필터링, 결합, 디테일을 설정하기 위해서는 필요
필터링을 위해서는 from altair import datum
트랜스폼
결합
스케일 & 가이드
데이터 컬럼과 x축, y축, 색상, 크기 등 encoding channel 간의 연결 정의
차트에 값 표시 가능, 데이터 설명 표시
grouping된 데이터가 아닌 unpivot(pd.melt)가 된 데이터를 활용해야 됨
import altair as alt df = pd.read_csv('https://raw.githubusercontent.com/huhshin/streamlit/master/data_retail.csv') # unpivot df_melted = pd.melt(df, id_vars=['date'], var_name='teams', value_name='sales') col1, col2 = st.columns(2) with col1: st.text('원본 데이터') st.write(df) with col2: st.text('변경 데이터') st.write(df_melted)
Python
복사
chart = alt.Chart(df_melted, title='일별 팀 매출 비교').mark_line().encode( x='date', y='sales', color='teams', strokeDash='teams'). properties(width=650, height=350) st.altair_chart(chart, use_container_width=True)
Python
복사
# Altair bar chart chart = alt.Chart(df_melted, title='일별 매출').mark_bar().encode( x='date', y='sales', color='teams') text = alt.Chart(df_melted).mark_text(dx=0, dy=0, color='black').encode( x='date',y='sales', text=alt.Text('sales:Q')) # detail 생략 가능 st.altair_chart(chart + text, use_container_width=True)
Python
복사
# Altair Scatter chart iris = pd.read_csv('https://raw.githubusercontent.com/huhshin/streamlit/master/data_iris.csv') st.write(iris) # caption으로 'sepal:꽃받침, petal:꽃잎' 설명 출력하기 st.caption('sepal : 꽃받침, petal : 꽃잎') # petal_length, petal_width로 Altair Circle chart 그리기 chart = alt.Chart(iris).mark_circle().encode( x='petal_length', y='petal_width', color='species') st.altair_chart(chart, use_container_width=True)
Python
복사
Plotly chart
반응형, 오픈소스 그리고 브라우저 기반 시각화 라이브러리
30개 종류의 차트를 가지고 있고, 3D 그래프도 지원
기존 matplotlib 함수랑 코드 유사
plotly express
독립 실행형 라이브러리
< 기본 코드 >
import plotly.graph_objects as go fig = go.Figure() fig.add_trace(go.Scatter(y=[2,1,4,3])) fig.add_trace(go.Bar(y=[1,4,3,2]))
Python
복사
import plotly.express as px df = px.data.iris() fig = px.scatter(df, x='sepal_width', y='sepal_length', color='species') fig.show() # 바로 이미지 확인 # express 로 이미지 출력 fig.write_image()
Python
복사
medal = pd.read_csv('https://raw.githubusercontent.com/huhshin/streamlit/master/data_medal.csv') st.write(medal) # plotly pie/donut chart fig = px.pie(medal, names='nation', values='gold', title='올림픽 양궁 금메달 현황', hole=.3) # 이미 생성된 그래프의 trace(데이터를 나타내는 개별 그래프 요소)를 업데이트하는 데 사용됨 # 특정 속성(색상, 라인 스타일, 마커 크기 등)을 수정할 수 있도록 해줌 # 차트 유형에 따라 옵션 값은 달라짐 fig.update_trace(textposition='inside', textinfo='percent+label') # plotly에서 그래프의 레이아웃을 업데이트하는 메서드 # 전체적인 레이아웃 요소(축,제목,범례, 배경 색상, 폰트 등)를 조정할 수 있다. fig.update_layout(font=dict(size=14)) # 범례 표시 제거 fig.update(layout_showlegend=False) st.plotly_chart(fig)
Python
복사
Plotly Bar chart

st. map

점으로 지도상에 위치를 표시한다
값을 보여주거나 원 크기 조절은 불가능하다
# 위도 : latitude 경도 : longitude data = pd.DataFrame({ 'lat' : [-34,49,-38,....], 'lon' : [-58,2,145,....]}) # 지도 그리기 st.map(data, latitude='lat', longitude='lon')
Python
복사

folium.map

Leaflet.js 를 기반으로 한 지도 시각화 라이브러리
파이썬 라이브러리인 Folium에서 제공하는 클래스
지도 생성
마커, 값 추가
html 출력
아나콘다에서 pip install folium
folium.Map() : Folium에서 지도 객체를 생성
location : 지도가 초기에 어떤 위치에서 시작할지를 정의
zoom_start : 지도의 초기 확대 수준(default =10, 숫자가 클수록 확대)
import folium map_data = pd.DataFrame({ 'lat': [-34, 49, -38, 59.93, 5.33, 45.52, -1.29, -12.97], 'lng': [-58, 2, 145, 30.32, -4.03, -73.57, 36.82, -38.5], 'name': ['Buenos Aires', 'Paris', 'Melbourne', 'St Petersburg', 'Abidjan', 'Montreal', 'Nairobi', 'Salvador'], 'value': [10, 12, 40, 70, 23, 43, 100, 43] }) my_map = folium.Map(location=[map_data['lat'].mean(), map_data['lng'].mean()+30], zoom_start=2)
Python
복사
for index, row in map_data.iterrows(): folium.CircleMarker( location=[row['lat'],row['lng']], radius=row['value']/5, color='pink', fill=True, fill_opacity=1.0 ).add_to(my_map) folium.Marker( location=[row['lat'],row['lng']], icon=folium.DivIcon(html=f"<div>{row['name']} {row['value']}</div>") ).add_to(my_map)
Python
복사
# 지도 그리기 # st.components.v1.html : Streamlit 라이브러리의 components 모듈에서 html 함수 사용 # .repr_html_() : 지도를 HTML 형식으로 표시 st.components.v1.html(my_map._repr_html_(), width=800, height=600)
Python
복사