Streamlit์ Python ๊ธฐ๋ฐ์ ์คํ์์ค ์น ์ ํ๋ฆฌ์ผ์ด์ ํ๋ ์์ํฌ๋ก, ๋ฐ์ดํฐ ์ฌ์ด์ธ์ค ๋ฐ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ๋น ๋ฅด๊ฒ ๋ฐฐํฌํ๊ณ ๊ณต์ ํ ์ ์๋๋ก ์ค๊ณ๋ ๋๊ตฌ์ ๋๋ค.
๐บ ๊ณต์ ์๊ฐ ์์: Streamlit Crash Course
๊ฐํธํ ๊ตฌํ:
๋ฐฑ์๋ ๊ฐ๋ฐ ๋ถํ์:
์๋ ๋ฆฌ๋ ๋๋ง:
๋ฐฐํฌ ๊ธฐ๋ฅ ์ง์:
์ธํฐ๋ํฐ๋ธ UI ์ ๊ณต:
๋ค์ํ ์ฐจํธ ๋ฐ ์ง๋ ์ง์:
์ปค๋ฎค๋ํฐ ๋ฐ ํ์ฅ ๊ธฐ๋ฅ ์ง์:
pip install streamlit
streamlit hello
ํด๋น demo์๋ ์ํ ๋์๋ณด๋ ๋ฐ ๊ตฌํ ์ํ ์ฝ๋ snippet์ด ์กด์ฌํฉ๋๋ค.
@st.cache_data
def get_UN_data():
AWS_BUCKET_URL = "https://streamlit-demo-data.s3-us-west-2.amazonaws.com"
df = pd.read_csv(AWS_BUCKET_URL + "/agri.csv.gz")
return df.set_index("Region")
try:
df = get_UN_data()
countries = st.multiselect(
"Choose countries", list(df.index), ["China", "United States of America"]
)
if not countries:
st.error("Please select at least one country.")
else:
data = df.loc[countries]
data /= 1000000.0
st.subheader("Gross agricultural production ($B)")
st.dataframe(data.sort_index())
data = data.T.reset_index()
data = pd.melt(data, id_vars=["index"]).rename(
columns={"index": "year", "value": "Gross Agricultural Product ($B)"}
)
chart = (
alt.Chart(data)
.mark_area(opacity=0.3)
.encode(
x="year:T",
y=alt.Y("Gross Agricultural Product ($B):Q", stack=None),
color="Region:N",
)
)
st.altair_chart(chart, use_container_width=True)
except URLError as e:
st.error(f"This demo requires internet access. Connection error: {e.reason}")
progress_bar = st.sidebar.progress(0)
status_text = st.sidebar.empty()
last_rows = np.random.randn(1, 1)
chart = st.line_chart(last_rows)
for i in range(1, 101):
new_rows = last_rows[-1, :] + np.random.randn(5, 1).cumsum(axis=0)
status_text.text(f"{i}% complete")
chart.add_rows(new_rows)
progress_bar.progress(i)
last_rows = new_rows
time.sleep(0.05)
progress_bar.empty()
# Streamlit widgets automatically run the script from top to bottom. Since
# this button is not connected to any other logic, it just causes a plain
# rerun.
st.button("Rerun")
@st.cache_data
def from_data_file(filename):
url = (
"https://raw.githubusercontent.com/streamlit/"
"example-data/master/hello/v1/%s" % filename
)
return pd.read_json(url)
try:
ALL_LAYERS = {
"Bike rentals": pdk.Layer(
"HexagonLayer",
data=from_data_file("bike_rental_stats.json"),
get_position=["lon", "lat"],
radius=200,
elevation_scale=4,
elevation_range=[0, 1000],
extruded=True,
),
"Bart stop exits": pdk.Layer(
"ScatterplotLayer",
data=from_data_file("bart_stop_stats.json"),
get_position=["lon", "lat"],
get_color=[200, 30, 0, 160],
get_radius="[exits]",
radius_scale=0.05,
),
"Bart stop names": pdk.Layer(
"TextLayer",
data=from_data_file("bart_stop_stats.json"),
get_position=["lon", "lat"],
get_text="name",
get_color=[0, 0, 0, 200],
get_size=10,
get_alignment_baseline="'bottom'",
),
"Outbound flow": pdk.Layer(
"ArcLayer",
data=from_data_file("bart_path_stats.json"),
get_source_position=["lon", "lat"],
get_target_position=["lon2", "lat2"],
get_source_color=[200, 30, 0, 160],
get_target_color=[200, 30, 0, 160],
auto_highlight=True,
width_scale=0.0001,
get_width="outbound",
width_min_pixels=3,
width_max_pixels=30,
),
}
st.sidebar.subheader("Map layers")
selected_layers = [
layer
for layer_name, layer in ALL_LAYERS.items()
if st.sidebar.checkbox(layer_name, True)
]
if selected_layers:
st.pydeck_chart(
pdk.Deck(
map_style=None,
initial_view_state={
"latitude": 37.76,
"longitude": -122.4,
"zoom": 11,
"pitch": 50,
},
layers=selected_layers,
)
)
else:
st.error("Please choose at least one layer above.")
except URLError as e:
st.error(
"""
**This demo requires internet access.**
Connection error: %s
"""
% e.reason
)
# Interactive Streamlit elements, like these sliders, return their value.
# This gives you an extremely simple interaction model.
iterations = st.sidebar.slider("Level of detail", 2, 20, 10, 1)
separation = st.sidebar.slider("Separation", 0.7, 2.0, 0.7885)
# Non-interactive elements return a placeholder to their location
# in the app. Here we're storing progress_bar to update it later.
progress_bar = st.sidebar.progress(0)
# These two elements will be filled in later, so we create a placeholder
# for them using st.empty()
frame_text = st.sidebar.empty()
image = st.empty()
m, n, s = 960, 640, 400
x = np.linspace(-m / s, m / s, num=m).reshape((1, m))
y = np.linspace(-n / s, n / s, num=n).reshape((n, 1))
for frame_num, a in enumerate(np.linspace(0.0, 4 * np.pi, 100)):
# Here were setting value for these two elements.
progress_bar.progress(frame_num)
frame_text.text("Frame %i/100" % (frame_num + 1))
# Performing some fractal wizardry.
c = separation * np.exp(1j * a)
Z = np.tile(x, (n, 1)) + 1j * np.tile(y, (1, m))
C = np.full((n, m), c)
M: Any = np.full((n, m), True, dtype=bool)
N = np.zeros((n, m))
for i in range(iterations):
Z[M] = Z[M] * Z[M] + C[M]
M[np.abs(Z) > 2] = False
N[M] = i
# Update the image placeholder by calling the image() function on it.
image.image(1.0 - (N / N.max()), use_container_width=True)
# We clear elements by calling empty on them.
progress_bar.empty()
frame_text.empty()
# Streamlit widgets automatically run the script from top to bottom. Since
# this button is not connected to any other logic, it just causes a plain
# rerun.
st.button("Rerun")
hello_streamlit.py
import streamlit as st
st.title("Hello Streamlit! ๐")
st.write("์ด๊ฒ์ Streamlit์ผ๋ก ๋ง๋ ๊ฐ๋จํ ์น ์ ํ๋ฆฌ์ผ์ด์
์
๋๋ค.")
streamlit run hello_streamlit.py
streamlit run
์ผ๋ก ํ์ด์ฌ ํจ์๋ฅผ ์คํํ์ฌ http://localhost:8501/
์์ Streamlit์ ์คํํ ์ ์์ต๋๋ค.๐ API DEMO ์ถ๋ ฅ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ ์๋ DataCamp์ ์ถ๋ ฅ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ฅผ ํ์ฉํ์ต๋๋ค.
- Image Source: https://www.datacamp.com/tutorial/streamlit
Image Source: https://www.datacamp.com/tutorial/streamlit
st.write()
์ค๋ช : ๋ฌธ์์ด, ์ซ์, ๋ฐ์ดํฐํ๋ ์, ๋ฆฌ์คํธ, ๊ฐ์ฒด ๋ฑ์ ์ถ๋ ฅํ ์ ์๋ ๋ฒ์ฉ ์ถ๋ ฅ ํจ์์ ๋๋ค.
์ฌ์ฉ ์์:
st.write("์๋
ํ์ธ์, Streamlit์
๋๋ค!")
st.write(12345)
Image Source: https://www.datacamp.com/tutorial/streamlit
st.title()
์ค๋ช : ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ชฉ์ ์ค์ ํ๋ ํจ์์ ๋๋ค. ๊ฐ์ฅ ํฐ ๊ธ์จ ํฌ๊ธฐ๋ก ํ์๋ฉ๋๋ค.
์ฌ์ฉ ์์:
st.title("Streamlit ์น ์ ํ๋ฆฌ์ผ์ด์
")
st.header()
์ค๋ช
: ํค๋(ํฐ ์ ๋ชฉ) ๋ฅผ ์ค์ ํ๋ ํจ์๋ก, st.title()
๋ณด๋ค ํฌ๊ธฐ๊ฐ ์์ง๋ง, ์ฃผ์ ์น์
์ ๋๋๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
์ฌ์ฉ ์์:
st.header("์ด๊ฒ์ ํค๋์
๋๋ค")
st.subheader()
์ค๋ช
: ์๋ธํค๋(์์ ๋ชฉ) ๋ฅผ ์ค์ ํ๋ ํจ์๋ก, st.header()
๋ณด๋ค ์์ ํฌ๊ธฐ์ ์ ๋ชฉ์
๋๋ค.
์ฌ์ฉ ์์:
st.subheader("์ด๊ฒ์ ์๋ธํค๋์
๋๋ค")
st.markdown()
์ค๋ช : Markdown ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ํ ์คํธ๋ฅผ ํฌ๋งทํ ์ ์์ต๋๋ค.
์ฌ์ฉ ์์:
st.markdown("# ํฐ ์ ๋ชฉ (Markdown)")
st.markdown("**๊ตต์ ๊ธ์จ**์ *์ดํค๋ฆญ์ฒด* ์ฌ์ฉ ๊ฐ๋ฅ")
st.caption()
์ค๋ช : ์ค๋ช ์ด๋ ์ฃผ์์ ๋ค๋ ์บก์ ์ ์ถ๊ฐํ๋ ํจ์๋ก, ์์ ๊ธ์จ๋ก ํ์๋ฉ๋๋ค.
์ฌ์ฉ ์์:
st.caption("์ด๊ฒ์ ์บก์
(์ค๋ช
)์
๋๋ค.")
st.code()
์ค๋ช : Python ์ฝ๋ ๋๋ ๋ค๋ฅธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด ์ฝ๋๋ฅผ ํ์ด๋ผ์ดํ ๋ ์ฝ๋ ๋ธ๋ก์ผ๋ก ์ถ๋ ฅํฉ๋๋ค.
์ฌ์ฉ ์์:
st.code("""
def hello():
print("Hello, Streamlit!")
""", language="python")
st.latex()
์ค๋ช : LaTeX ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ์์์ ๋ ๋๋งํ ์ ์์ต๋๋ค.
์ฌ์ฉ ์์:
st.latex(r"E = mc^2")
Image Source: https://www.datacamp.com/tutorial/streamlit
1. ํ
์คํธ ์
๋ ฅ (st.text_input()
)
์ค๋ช : ์ฌ์ฉ์๊ฐ ํ ์คํธ๋ฅผ ์ ๋ ฅํ ์ ์๋ ์ ๋ ฅ ์์๋ฅผ ์ ๊ณตํฉ๋๋ค.
์์ :
name = st.text_input("์ด๋ฆ์ ์
๋ ฅํ์ธ์")
st.write(f"์
๋ ฅ๋ ์ด๋ฆ: {name}")
2. ์ซ์ ์
๋ ฅ (st.number_input()
)
์ค๋ช : ์ฌ์ฉ์๊ฐ ์ซ์๋ฅผ ์ ๋ ฅํ ์ ์๋๋ก ํฉ๋๋ค.
์์ :
age = st.number_input("๋์ด๋ฅผ ์
๋ ฅํ์ธ์", min_value=0, max_value=100, step=1)
st.write(f"์
๋ ฅ๋ ๋์ด: {age}")
3. ๋ ์ง ์
๋ ฅ (st.date_input()
)
์ค๋ช : ์ฌ์ฉ์๊ฐ ๋ ์ง๋ฅผ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
์์ :
selected_date = st.date_input("๋ ์ง ์ ํ")
st.write(f"์ ํํ ๋ ์ง: {selected_date}")
4. ์๊ฐ ์
๋ ฅ (st.time_input()
)
์ค๋ช : ์ฌ์ฉ์๊ฐ ์๊ฐ์ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
์์ :
selected_time = st.time_input("์๊ฐ ์ ํ")
st.write(f"์ ํํ ์๊ฐ: {selected_time}")
5. ์ฌ๋ฌ ์ค ์
๋ ฅ (st.text_area()
)
์ค๋ช : ์ฌ๋ฌ ์ค์ ํ ์คํธ๋ฅผ ์ ๋ ฅํ ์ ์๋ ์ ๋ ฅ ํ๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
์์ :
message = st.text_area("๋ฉ์์ง๋ฅผ ์
๋ ฅํ์ธ์")
st.write(f"์
๋ ฅ๋ ๋ฉ์์ง:\n{message}")
6. ํ์ผ ์
๋ก๋ (st.file_uploader()
)
์ค๋ช : ์ฌ์ฉ์๊ฐ ํ์ผ์ ์ ๋ก๋ํ ์ ์๋๋ก ํฉ๋๋ค.
์์ :
uploaded_file = st.file_uploader("ํ์ผ์ ์
๋ก๋ํ์ธ์")
if uploaded_file is not None:
st.write("์
๋ก๋๋ ํ์ผ:", uploaded_file.name)
7. ์์ ์ ํ (st.color_picker()
)
์ค๋ช : ์์์ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
์์ :
color = st.color_picker("์์์ ์ ํํ์ธ์", <"#00f900")
st.write(f"์ ํํ ์์: {color}")
Image Source: https://www.datacamp.com/tutorial/streamlit
1. ๋ฒํผ (st.button()
)
์ค๋ช : ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํน์ ๋์์ ์คํํ ์ ์๋๋ก ํฉ๋๋ค.
์์ :
if st.button("ํด๋ฆญํ์ธ์"):
st.write("๋ฒํผ์ด ํด๋ฆญ๋์์ต๋๋ค!")
2. ์ฒดํฌ๋ฐ์ค (st.checkbox()
)
agree = st.checkbox("๋์ํฉ๋๋ค")
if agree:
st.write("๋์ํ์
จ์ต๋๋ค!")
3. ๋ผ๋์ค ๋ฒํผ (st.radio()
)
selected_option = st.radio("์ต์
์ ์ ํํ์ธ์", ("์ต์
1", "์ต์
2", "์ต์
3"))
st.write(f"์ ํ๋ ์ต์
: {selected_option}")
4. ๋๋กญ๋ค์ด ์ ํ (st.selectbox()
)
fruit = st.selectbox("๊ณผ์ผ์ ์ ํํ์ธ์", ["์ฌ๊ณผ", "๋ฐ๋๋", "์ค๋ ์ง"])
st.write(f"์ ํํ ๊ณผ์ผ: {fruit}")
5. ๋ค์ค ์ ํ (st.multiselect()
)
planets = st.multiselect("ํ์ฑ์ ์ ํํ์ธ์", ["๋ชฉ์ฑ", "ํ์ฑ", "ํด์์ฑ"])
st.write(f"์ ํํ ํ์ฑ: {planets}")
6. ์ฌ๋ผ์ด๋ (st.slider()
)
number = st.slider("์ซ์๋ฅผ ์ ํํ์ธ์", 0, 50)
st.write(f"์ ํ๋ ์ซ์: {number}")
7. ์ ํ ์ฌ๋ผ์ด๋ (st.select_slider()
)
rating = st.select_slider("ํ๊ฐ๋ฅผ ์ ํํ์ธ์", ["๋์จ", "๋ณดํต", "์ข์", "์ต๊ณ "])
st.write(f"์ ํํ ํ๊ฐ: {rating}")
1. ์ด๋ฏธ์ง, ๋น๋์ค ๋ฐ ์ค๋์ค ํ์ผ ์ถ๋ ฅ
(1) ์ด๋ฏธ์ง ์ถ๋ ฅ (st.image()
)
์ค๋ช
: ์ด๋ฏธ์ง๋ฅผ ์ถ๋ ฅํ๋ ํจ์์
๋๋ค. PIL.Image
๊ฐ์ฒด ๋๋ ์ด๋ฏธ์ง URL, ๋ก์ปฌ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์์ :
import streamlit as st
from PIL import Image
image = Image.open("example.jpg") - ๋ก์ปฌ ์ด๋ฏธ์ง ํ์ผ
st.image(image, caption="์์ ์ด๋ฏธ์ง", use_column_width=True)
(2) ์ค๋์ค ์ถ๋ ฅ (st.audio()
)
์ค๋ช : ์ค๋์ค ํ์ผ์ ์น์์ ์ฌ์ํ ์ ์๋๋ก ํฉ๋๋ค.
์์ :
st.audio("example.mp3")
(3) ๋น๋์ค ์ถ๋ ฅ (st.video()
)
์ค๋ช : ๋น๋์ค ํ์ผ์ ์น์์ ์ฌ์ํ ์ ์๋๋ก ํฉ๋๋ค.
์์ :
st.video("example.mp4")
2. ๋ฐ์ดํฐํ๋ ์ ์ถ๋ ฅ
pandas
๋ฐ์ดํฐํ๋ ์์ ์ฌ๋ฌ ๋ฐฉ์์ผ๋ก ํ์ํ ์ ์์ต๋๋ค.(1) ๊ธฐ๋ณธ ๋ฐ์ดํฐ ์ถ๋ ฅ (st.write()
)
์ค๋ช
: st.write()
๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐํ๋ ์์ ๊ธฐ๋ณธ์ ์ธ ํํ๋ก ์ถ๋ ฅํ ์ ์์ต๋๋ค.
์์ :
st.write(df)
(2) ์ธํฐ๋ํฐ๋ธ ๋ฐ์ดํฐํ๋ ์ (st.dataframe()
)
์ค๋ช
: st.dataframe()
์ ์ฌ์ฉํ๋ฉด ์คํฌ๋กค ๋ฐ ์ ๋ ฌ ๊ธฐ๋ฅ์ด ํฌํจ๋ ์ธํฐ๋ํฐ๋ธํ ๋ฐ์ดํฐํ๋ ์์ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
์์ :
st.dataframe(df)
(3) ์ ์ ํ
์ด๋ธ (st.table()
)
์ค๋ช
: st.table()
์ ์ ์ ์ธ ํ
์ด๋ธ ํํ๋ก ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๋ฉฐ, ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ด ํ์ ์์ ๋ ์ ์ฉํฉ๋๋ค.
์์ :
st.table(df)
3. JSON ๋ฐ์ดํฐ ์ถ๋ ฅ (st.json()
)
์ค๋ช : JSON ํํ์ ๋ฐ์ดํฐ๋ฅผ ๊ณ์ธต์ ์ผ๋ก ์ ๋ฆฌ๋ ํํ๋ก ์ถ๋ ฅํ ์ ์์ต๋๋ค.
์์ :
st.json({
'์ด๋ฆ': '์ด์ํ',
'๋์ด': 24,
'๊ฑฐ์ฃผ์ง': '๊ด์ฃผ'
})
4. ์ฃผ์ ์งํ ๋ฐ ํต๊ณ ์ถ๋ ฅ (st.metric()
)
delta
๊ฐ์ ์ค์ ํ๋ฉด ๋ณํ๋์ ํจ๊ป ํ์ํ ์ ์์ต๋๋ค.์์ (์งํ ์ถ๋ ฅ)
st.metric(label="LG์ ์", value="78,000์", delta="2.12%")
st.metric(label="ํ๋์ฐจ", value="150,000์", delta="-1.25%")
1. ์ฐจํธ ์ถ๋ ฅ
matplotlib
, pandas
, Altair
, Graphviz
๋ฑ์ ๊ทธ๋ํ๋ฅผ ์ฝ๊ฒ ์์ฑํ ์ ์์ต๋๋ค.(1) Matplotlib ๊ทธ๋ํ (st.pyplot()
)
์ค๋ช
: matplotlib.pyplot
์ ์ฌ์ฉํ์ฌ ์์ฑํ ๊ทธ๋ํ๋ฅผ Streamlit ์ฑ์ ํ์ํ ์ ์์ต๋๋ค.
Matplotlib
์ Python์์ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ์๊ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, ์ธ๋ฐํ ์ปค์คํฐ๋ง์ด์ง์ด ํ์ํ ๊ฒฝ์ฐ ์ ์ฉํฉ๋๋ค. import streamlit as st
import matplotlib.pyplot as plt
import numpy as np
rand = np.random.normal(1, 2, size=20) # ์ ๊ท๋ถํฌ ๋์ ์์ฑ
fig, ax = plt.subplots()
ax.hist(rand, bins=15) # ํ์คํ ๊ทธ๋จ ๊ทธ๋ฆฌ๊ธฐ
st.pyplot(fig)
Image Source: https://www.datacamp.com/tutorial/streamlit
(2) ์ ํ ์ฐจํธ (st.line_chart()
)
์ค๋ช : Pandas ๋ฐ์ดํฐํ๋ ์์ ์ด์ฉํ์ฌ ์ ํ ์ฐจํธ๋ฅผ ๊ทธ๋ฆฝ๋๋ค.
์์ :
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(10, 2), columns=['x', 'y'])
st.line_chart(df)
Image Source: https://www.datacamp.com/tutorial/streamlit
(3) ๋ง๋ ์ฐจํธ (st.bar_chart()
)
์ค๋ช : Pandas ๋ฐ์ดํฐํ๋ ์์ ์ด์ฉํ์ฌ ๋ง๋ ์ฐจํธ๋ฅผ ์์ฑํฉ๋๋ค.
์์ :
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(10, 2), columns=['x', 'y'])
st.bar_chart(df)
Image Source: https://www.datacamp.com/tutorial/streamlit
(4) ์์ญ ์ฐจํธ (st.area_chart()
)
์ค๋ช : Pandas ๋ฐ์ดํฐํ๋ ์์ ์ด์ฉํ์ฌ ์์ญ ์ฐจํธ๋ฅผ ์์ฑํฉ๋๋ค.
์์ :
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(10, 2), columns=['x', 'y'])
st.area_chart(df)
Image Source: https://www.datacamp.com/tutorial/streamlit
(5) Altair ์ฐจํธ (st.altair_chart()
)
์ค๋ช
: Altair
๋ฅผ ์ฌ์ฉํ์ฌ ์ธํฐ๋ํฐ๋ธํ ์ฐจํธ๋ฅผ ์์ฑํฉ๋๋ค.
์์ :
import streamlit as st
import pandas as pd
import numpy as np
import altair as alt
df = pd.DataFrame(np.random.randn(500, 3), columns=['x', 'y', 'z'])
chart = alt.Chart(df).mark_circle().encode(
x='x', y='y', size='z', color='z', tooltip=['x', 'y', 'z']
)
st.altair_chart(chart, use_container_width=True)
Image Source: https://www.datacamp.com/tutorial/streamlit
(6) ๊ทธ๋ํ ๊ตฌ์กฐ ์๊ฐํ (st.graphviz_chart()
)
์ค๋ช
: graphviz
๋ฅผ ์ด์ฉํด ๋
ธ๋ ๋ฐ ์ฃ์ง ๊ธฐ๋ฐ ๊ทธ๋ํ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
์์ :
import streamlit as st
import graphviz
st.graphviz_chart('''
digraph {
Big_shark -> Tuna
Tuna -> Mackerel
Mackerel -> Small_fishes
Small_fishes -> Shrimp
}
''')
Image Source: https://www.datacamp.com/tutorial/streamlit
2. ์ง๋ ์ถ๋ ฅ
st.map()
ํจ์๋ฅผ ์ด์ฉํ์ฌ ์ง๋๋ฅผ ํ์ํ ์ ์์ผ๋ฉฐ, latitude
(์๋) ๋ฐ longitude
(๊ฒฝ๋) ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๊ฐํํ ์ ์์ต๋๋ค.์ง๋ ์ถ๋ ฅ (st.map()
)
์ค๋ช : Pandas ๋ฐ์ดํฐํ๋ ์์ ์๋(lat)์ ๊ฒฝ๋(lon) ๊ฐ์ ํฌํจํ์ฌ ์ง๋๋ฅผ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
lat
)์ ๊ฒฝ๋(lon
) ๊ฐ์ด ํฌํจ๋ ๋ฐ์ดํฐ๊ฐ ํ์ํฉ๋๋ค.์์ :
import pandas as pd
import numpy as np
import streamlit as st
df = pd.DataFrame(
np.random.randn(500, 2) / [50, 50] + [37.76, -122.4], # ์ํ๋์์ค์ฝ ์ฃผ๋ณ ๋๋ค ์ขํ ์์ฑ
columns=['lat', 'lon']
)
st.map(df)
Image Source: https://www.datacamp.com/tutorial/streamlit
1. ์งํ๋ฅ ๋ฐ ๋ก๋ฉ ์ํ ํ์
Image Source: https://www.datacamp.com/tutorial/streamlit
(1) ์งํ๋ฅ ๋ฐ (st.progress()
)
์ค๋ช : ํ๋ก์ธ์ค ์งํ ์ํฉ์ ๋ํ๋ด๋ ์งํ๋ฅ ๋ฐ(progress bar) ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
์์ :
import streamlit as st
import time
progress_bar = st.progress(0) # ์ด๊ธฐ๊ฐ 0
for percent in range(0, 101, 10):
time.sleep(0.1) # ํ๋ก์ธ์ค ์งํ ์๋ฎฌ๋ ์ด์
progress_bar.progress(percent) # ์งํ๋ฅ ์
๋ฐ์ดํธ
(2) ์คํผ๋ (st.spinner()
)
์ค๋ช : ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ์์ ์ค ๋ก๋ฉ ๋ฉ์์ง๋ฅผ ํ์ํ๋ ๊ธฐ๋ฅ์ ๋๋ค.
์์ :
import streamlit as st
import time
with st.spinner("์ ์๋ง ๊ธฐ๋ค๋ ค ์ฃผ์ธ์..."):
time.sleep(5) # ๋๊ธฐ ์๊ฐ ์๋ฎฌ๋ ์ด์
st.success("์์
์๋ฃ!")
(3) ์ถํ ์ ๋๋ฉ์ด์
(st.balloons()
)
์ค๋ช : ์ฌ์ฉ์๊ฐ ์์ ์ ์๋ฃํ์ ๋ ํ์ ์ ๋๋ฉ์ด์ ์ ํ์ํ์ฌ ์ถํํ ์ ์์ต๋๋ค.
์์ :
import streamlit as st
st.success("์์
์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ต๋๋ค!")
st.balloons() # ์ถํ ์ ๋๋ฉ์ด์
2. ์ํ ๋ฉ์์ง ์ถ๋ ฅ
Image Source: https://www.datacamp.com/tutorial/streamlit
(1) ์ฑ๊ณต ๋ฉ์์ง (st.success()
)
st.success("์ถํํฉ๋๋ค! ๋ชจ๋ ์์
์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ต๋๋ค.")
(2) ์ค๋ฅ ๋ฉ์์ง (st.error()
)
st.error("์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.")
(3) ๊ฒฝ๊ณ ๋ฉ์์ง (st.warning()
)
st.warning("์ด ์์
์ ์ฃผ์๊ฐ ํ์ํฉ๋๋ค.")
(4) ์ ๋ณด ๋ฉ์์ง (st.info()
)
st.info("Streamlit์ ์ฌ์ฉํ๋ฉด ์ฝ๊ฒ ์น ์ฑ์ ๋ง๋ค ์ ์์ต๋๋ค.")
(5) ์์ธ ๋ฉ์์ง (st.exception()
)
st.exception(RuntimeError("RuntimeError ์์ธ ๋ฐ์"))
Streamlit์ ๋ค์ํ UI ์์๋ฅผ ์ ๊ณตํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณด๋ค ๊ตฌ์กฐ์ ์ผ๋ก ์ ๋ฆฌํ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ด ์ฅ์์๋ ์ฌ์ด๋๋ฐ, ์ปจํ ์ด๋, ์ปฌ๋ผ, ํญ, ์ต์คํฌ๋(expander) ๋ฑ์ ๊ธฐ๋ฅ์ ์ ๋ฆฌํ๊ฒ ์ต๋๋ค.
Streamlit์ st.sidebar()
๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋ฉด์ ์ผ์ชฝ์ ๊ณ ์ ๋ ์ฌ์ด๋๋ฐ(Sidebar) ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
(1) ์ฌ์ด๋๋ฐ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
์ค๋ช
: st.sidebar
๋ฅผ ์ฌ์ฉํ๋ฉด ์ฑ์ ์ฃผ์ ์ฝํ
์ธ ๋ฅผ ๋ฐฉํดํ์ง ์๊ณ ์ต์
, ์
๋ ฅ ํ๋, ๋ฒํผ ๋ฑ์ ๋ฐฐ์นํ ์ ์์ต๋๋ค.
์์ :
import streamlit as st
st.sidebar.title("์ฌ์ด๋๋ฐ ๋ฉ๋ด")
st.sidebar.markdown("์ฌ๊ธฐ์ ์ค์ ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.")
# ์ฌ์ด๋๋ฐ ์์ ์ถ๊ฐ
option = st.sidebar.radio("์ต์
์ ํ", ["์ต์
A", "์ต์
B", "์ต์
C"])
st.sidebar.button("์ฌ์ด๋๋ฐ ๋ฒํผ")
๐ ์ฃผ์ ํน์ง
st.sidebar.title()
, st.sidebar.markdown()
, st.sidebar.radio()
๋ฑ์ ์ฌ์ฉํ์ฌ ์ฌ์ด๋๋ฐ ๋ด UI ๊ตฌ์ฑ ๊ฐ๋ฅ Streamlit์์๋ st.columns()
์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฐ์ ์ปฌ๋ผ์ ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํ์ฉํ๋ฉด ๋ ์ด์์์ ๋ ์ ๋ํ ์ ์์ต๋๋ค.
(1) ๋์ผํ ๋๋น์ ์ปฌ๋ผ ์์ฑ
์ค๋ช
: st.columns(n)
์ ์ฌ์ฉํ๋ฉด n
๊ฐ์ ๋์ผํ ํฌ๊ธฐ์ ์ปฌ๋ผ์ด ์์ฑ๋ฉ๋๋ค.
์์ :
col1, col2 = st.columns(2)
col1.write("์ฒซ ๋ฒ์งธ ์ปฌ๋ผ")
col2.write("๋ ๋ฒ์งธ ์ปฌ๋ผ")
(2) ๋ค์ํ ๋๋น์ ์ปฌ๋ผ ์์ฑ
์ค๋ช
: st.columns([๋น์จ1, ๋น์จ2, ...])
์ ์ฌ์ฉํ๋ฉด ๋น์จ์ ์ง์ ํ์ฌ ๊ฐ๋ณ์ ์ธ ๋๋น์ ์ปฌ๋ผ์ ์์ฑํ ์ ์์ต๋๋ค.
์์ :
col1, col2, col3 = st.columns([2, 6, 2])
with col1:
st.header('Col1')
st.image('https://static.streamlit.io/examples/cat.jpg')
with col2:
st.header('Col2')
st.image('https://static.streamlit.io/examples/dog.jpg')
with col3:
st.header('Col3')
st.image('https://static.streamlit.io/examples/owl.jpg')
๐ ์ฃผ์ ํน์ง
Streamlit์์๋ st.container()
๋ฅผ ์ฌ์ฉํ์ฌ ๋ด์ฉ์ ๊ทธ๋ฃนํํ ์ ์์ต๋๋ค.
(1) ์ปจํ ์ด๋ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
์ค๋ช
: st.container()
์์ ์์๋ฅผ ๋ฐฐ์นํ๋ฉด ๋
ผ๋ฆฌ์ ์ธ ๊ทธ๋ฃน์ ๋ง๋ค ์ ์์ต๋๋ค.
์์ :
with st.container():
st.write("์ด๊ฒ์ ์ปจํ
์ด๋ ๋ด๋ถ์
๋๋ค.")
๐ ์ฃผ์ ํน์ง
Streamlit์ st.tabs()
๋ฅผ ์ฌ์ฉํ๋ฉด ํ ํ๋ฉด์์ ์ฌ๋ฌ ๊ฐ์ ํญ์ ํ์ฉํ ์ ์์ต๋๋ค.
(1) ๊ธฐ๋ณธ์ ์ธ ํญ ์์ฑ
์ค๋ช
: st.tabs(["ํญ ์ด๋ฆ1", "ํญ ์ด๋ฆ2", ...])
์ ์ฌ์ฉํ์ฌ ํญ์ ์์ฑํ๊ณ , ๊ฐ ํญ์ ์ฝํ
์ธ ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
์์ :
tab1, tab2, tab3 = st.tabs(['Cat', 'Dog', 'Owl'])
with tab1:
st.header('๊ณ ์์ด')
st.image('https://static.streamlit.io/examples/cat.jpg')
with tab2:
st.header('๊ฐ์์ง')
st.image('https://static.streamlit.io/examples/dog.jpg')
with tab3:
st.header('์ฌ๋นผ๋ฏธ')
st.image('https://static.streamlit.io/examples/owl.jpg')
๐ ์ฃผ์ ํน์ง
Streamlit์์๋ st.expander()
๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ณด๋ฅผ ์ ๊ณ ํผ์น๋ UI๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
(1) ๊ธฐ๋ณธ์ ์ธ Expander ์ฌ์ฉ๋ฒ
์ค๋ช
: st.expander("์ ๋ชฉ")
์ ์ฌ์ฉํ์ฌ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ํ ์๋ ๋ธ๋ก์ ๋ง๋ค๊ณ , ํด๋ฆญ ์ ๋ด์ฉ์ ํผ์น ์ ์์ต๋๋ค.
์์ :
with st.expander("๋ ๋ณด๊ธฐ"):
st.write("์ด๊ณณ์ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์
๋ ฅํ ์ ์์ต๋๋ค.")
(2) Expander ๋ด๋ถ์ ์ด๋ฏธ์ง ๋ฐ ํ ์คํธ ์ถ๊ฐ
์ค๋ช
: st.expander()
๋ด๋ถ์ ์ฌ๋ฌ ๊ฐ์ง ์์๋ฅผ ๋ฃ์ ์ ์์ต๋๋ค.
์์ :
with st.expander("๊ณ ์์ด ์ ๋ณด ๋ณด๊ธฐ"):
st.write("์ฌ๊ธฐ์๋ ๊ณ ์์ด์ ๋ํ ์ ๋ณด๊ฐ ๋ค์ด๊ฐ๋๋ค.")
st.image('https://static.streamlit.io/examples/cat.jpg', width=200)
๐ ์ฃผ์ ํน์ง
(์ฐธ๊ณ ) ๊ธฐ๋ณธ์ ์ผ๋ก ์คํํ๋ฉด?
streamlit run app.py
- ๊ธฐ๋ณธ์ ์ผ๋ก localhost:8501 ์์ ์คํ๋จ.
- localhost๋ 127.0.0.1๋ก ๋งคํ๋๋ฉฐ, ์ธ๋ถ์์๋ ์ ๊ทผํ ์ ์์.
- ์ฆ, ๊ฐ์ PC์์๋ง ์ ๊ทผ ๊ฐ๋ฅํ๊ณ , ๋ค๋ฅธ ๋คํธ์ํฌ ๊ธฐ๊ธฐ(์: ์ค๋งํธํฐ, ๋ค๋ฅธ ์ปดํจํฐ)์์๋ ์ ์ํ ์ ์์.
8080
ํฌํธ์์ ์คํ๋จ.streamlit run app.py --server.port 8080
โ ์ ํน์ ํฌํธ๋ฅผ ๋ณ๊ฒฝํ ๊น?
- ํฌํธ ์ถฉ๋ ๋ฐฉ์ง: ์ด๋ฏธ 8501 ํฌํธ๋ฅผ ๋ค๋ฅธ ์๋น์ค๊ฐ ์ฌ์ฉ ์ค์ผ ์๋ ์์.
- ๊ธฐ๋ณธ ๋ฐฉํ๋ฒฝ ์ ์ฑ ์ฐํ: ์ผ๋ถ ๋คํธ์ํฌ ํ๊ฒฝ์์๋ ํน์ ํฌํธ(์: 8501)๊ฐ ์ฐจ๋จ๋ ์ ์์.
- ๊ณต์ ๋ ์๋ฒ์์ ๋ค๋ฅธ ์๋น์ค์ ๊ตฌ๋ถ: ๋์ผํ ์๋ฒ์์ ์ฌ๋ฌ Streamlit ์ฑ์ ์คํํ ๋ ํฌํธ๋ฅผ ๋ค๋ฅด๊ฒ ์ค์ ํด์ผ ํจ.
http://<์๋ฒ IP>:8080
์ผ๋ก ์ ์ ๊ฐ๋ฅstreamlit run app.py --server.address 0.0.0.0 --server.port 8080
โ ์ฌ๊ธฐ์ 0.0.0.0์ด ๋ฌด์์ธ๊ฐ?
- ๊ธฐ๋ณธ์ ์ผ๋ก Streamlit์
localhost(127.0.0.1)
์์๋ง ์คํ๋๋ฏ๋ก, ์ธ๋ถ์์๋ ์ ๊ทผํ ์ ์์.0.0.0.0
์ผ๋ก ์ค์ ํ๋ฉด ํด๋น ์ปดํจํฐ์ ๋ชจ๋ ๋คํธ์ํฌ ์ธํฐํ์ด์ค์์ ์ ๊ทผ ๊ฐ๋ฅ.- ์ฆ, ๊ฐ์ ๋คํธ์ํฌ์ ๋ค๋ฅธ ๊ธฐ๊ธฐ์์๋
http://<์๋ฒ์ IP>:8080
์ ํตํด ์ ๊ทผ ๊ฐ๋ฅ.
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0", "--server.port=8501"]
docker build -t my-streamlit-app .
docker run -p 8501:8501 my-streamlit-app
๐ ์ด์ http://<์๋ฒ IP>:8501
์์ ์ ๊ทผ ๊ฐ๋ฅ!
โน๏ธ Streamlit ์ปค๋ฎค๋ํฐ ๋ฐ ํ์ต ์๋ฃ
๐ฏ ์ ๋ฆฌ
Streamlit
์ ๊ฐ๋จํ ํ์ด์ฌ ์ฝ๋๋ง์ผ๋ก ์น/์ฑ ๋์๋ณด๋๋ฅผ ๋ง๋ค ์ ์๋ ์ต๊ณ ์ ๋๊ตฌ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค ๐