๐Ÿ˜Ž ๊ณต๋ถ€ํ•˜๋Š” ์ง•์ง•์•ŒํŒŒ์นด๋Š” ์ฒ˜์Œ์ด์ง€?

VSCode ์— Dash ์‹คํ–‰ํ•˜๊ธฐ ๋ณธ๋ฌธ

๐Ÿ‘ฉ‍๐Ÿ’ป ์ธ๊ณต์ง€๋Šฅ (ML & DL)/Serial Data

VSCode ์— Dash ์‹คํ–‰ํ•˜๊ธฐ

์ง•์ง•์•ŒํŒŒ์นด 2022. 9. 27. 10:55
728x90
๋ฐ˜์‘ํ˜•

220927 ์ž‘์„ฑ

<๋ณธ ๋ธ”๋กœ๊ทธ๋Š” dschloe ๋‹˜์˜ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค :-) >

https://dschloe.github.io/python/dash/dash_project/

 

Python Dash๋ฅผ ํ™œ์šฉํ•œ ๋Œ€์‹œ๋ณด๋“œ ๋งŒ๋“ค๊ธฐ with Heroku

๊ฐ•์˜ ํ™๋ณด ์ทจ์ค€์ƒ์„ ์œ„ํ•œ ๊ฐ•์˜๋ฅผ ์ œ์ž‘ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋ณธ ๋ธ”๋กœ๊ทธ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ•์˜๋ฅผ ์ˆ˜๊ฐ•ํ•˜์‹  ๋ถ„์€ ๊ฒŒ์‹œ๊ธ€ ์ œ๋ชฉ๊ณผ ๋งํฌ๋ฅผ ์ˆ˜๊ฐ•ํ•˜์—ฌ ์ธํ”„๋Ÿฐ ๋ฉ”์‹œ์ง€๋ฅผ ํ†ตํ•ด ๋ณด๋‚ด์ฃผ์‹œ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์Šคํƒ€๋ฒ…์Šค ์•„์ด์Šค ์•„

dschloe.github.io

 

 

 

1๏ธโƒฃ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘

https://www.kaggle.com/neuromusic/avocado-prices

avocado.csv

 

2๏ธโƒฃ anaconda ๊ฐ€์ƒํ™˜๊ฒฝ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

  • ๊ฐ€์ƒํ™˜๊ฒฝ 
$ conda create --name ๊ฐ€์ƒํ™˜๊ฒฝ์ด๋ฆ„ python=3.8
$ conda activate ๊ฐ€์ƒํ™˜๊ฒฝ์ด๋ฆ„
  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ 
$ conda install dash
$ conda install pandas
$ conda install colorama
  • dash ์„ค์น˜์—์„œ error ๋ฐœ์ƒ

๋‚œ ๊ตฌ๊ธ€๋งํ•ด์„œ ํ•˜๋ผ๋Š”๊ฑฐ ๋ฌด์ž‘์ •..ํ•ด๋ฒ„๋ฆผ

๊ทธ๋Ÿฌ๋ฉด ์–ด๋Š ์ˆœ๊ฐ„ ๋˜์–ด์žˆ์Œ

sudo apt-get install python

sudo python -m pip install dash==version

 

โž• test

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

# assume you have a "long-form" data frame
# see https://plotly.com/python/px-arguments/ for more options
df = pd.DataFrame({
    "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
    "Amount": [4, 1, 2, 2, 4, 5],
    "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
})

fig = px.bar(df, x="Fruit", y="Amount", color="City", barmode="group")

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    '''),

    dcc.Graph(
        id='example-graph',
        figure=fig
    )
])

if __name__ == '__main__':
    app.run_server(debug=True,host = '127.0.0.1')

https://dash.plotly.com/layout

  • socket error
sudo apt update -y

sudo apt-get install openssh-server

=> ๋งจ๋ฐ‘ ์„œ๋ฒ„ ๋ฐฐํฌ ์ฝ”๋“œ ์—์„œ host ๋‹ค์‹œ ์ง€์ •

if __name__ == '__main__':
    app.run_server(debug=True,host = '127.0.0.1')

 

 

 

 

 

 

3๏ธโƒฃ ๋Œ€์‹œ ๋ณด๋“œ ์ฝ”๋“œ ์ž‘์„ฑ

๐Ÿ’› ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ฐ Dash ํด๋ž˜์Šค ์ •์˜

# 1. data load
import dash                             # ๋Œ€์‹œ๋ณด๋“œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ดˆ๊ธฐํ™”
import dash_core_components as dcc      # ๋™์  ๊ตฌ์„ฑ์š”์†Œ๋“ค(์˜ˆ: ๊ทธ๋ž˜ํ”„, ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด, ๋‚ ์งœ ๊ธฐ๊ฐ„ ๋“ฑ) ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ธฐ๋Šฅ
import dash_html_components as html     # html ํƒœ๊ทธ์— ์ ‘๊ทผ
import pandas as pd                     # ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ฐ ๊ฐ€๊ณต์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜ ์ง€์›

# step 2. Data Import
data = pd.read_csv("coding/220926/avocado.csv", index_col=0)
data = data.query("type == 'conventional' and region == 'Albany'")      # type = conventional ๊ณผ, region = Albany ๋งŒ ์ถ”์ถœํ•˜๋Š” ํ–‰์„ ์ถ”์ถœ
data["Date"] = pd.to_datetime(data["Date"], format="%Y-%m-%d")          
data.sort_values("Date", inplace=True)                                  # ๋‚ ์งœ์˜ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ์ฝ”๋“œ

# step 3. Dash Class
app = dash.Dash(__name__)

 

 

๐Ÿ’› ๋Œ€์‹œ๋ณด๋“œ HTML Layout

# step 4. HTML
app.layout = html.Div(                              # ์ผ์ข…์˜ parent component
	  # Header Message
    children=[
        html.H1(children="Temp Analytics",),        # html.h1์€ h1 ํƒœ๊ทธ, html.p์€ p ํƒœ๊ทธ
        html.P(
            children="Temp",
        ),
        # ๊ทธ๋ž˜ํ”„		
        dcc.Graph(                                  # ๊ทธ๋ž˜ํ”„๊ฐ€ ๊ตฌํ˜„๋˜๋Š” ์ฝ”๋“œ
            figure={
                "data": [
                    {
                        "x": data["Date"],
                        "y": data["AveragePrice"],
                        "type": "lines",
                    },
                ],
                "layout": {"title": "Title_1"},
            },
        ),
        dcc.Graph(                                  # ๊ทธ๋ž˜ํ”„๊ฐ€ ๊ตฌํ˜„๋˜๋Š” ์ฝ”๋“œ
            figure={
                "data": [
                    {
                        "x": data["Date"],
                        "y": data["Total Volume"],
                        "type": "lines",
                    },
                ],
                "layout": {"title": "Title_2"},
            },
        ),
    ]
)
  • Dash HTML Components
    • HTML components์šฉ Wrappers๋ฅผ ์ œ๊ณต => ๋ฌธ๋‹จ, ์ œ๋ชฉ ๋˜๋Š” ๋ชฉ๋ก๊ณผ ๊ฐ™์€ ์š”์†Œ๋ฅผ ์ž‘์„ฑ
  • Dash Core Components
    • ๋Œ€ํ™”ํ˜• ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ Python ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณต => ๊ทธ๋ž˜ํ”„, ์Šฌ๋ผ์ด๋” ๋˜๋Š” ๋“œ๋กญ๋‹ค์šด๊ณผ ๊ฐ™์€ interactive elements๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ

 

๐Ÿ’› ๋Œ€์‹œ๋ณด๋“œ ๋ฐฐํฌ (localhost)

# step 5. dash board release (localhost)
"""
Flask ๊ธฐ๋ฐ˜์˜ ์„œ๋ฒ„๋กœ ์ž‘๋™
ํŒŒ๋ผ๋ฏธํ„ฐ debug=True ๋ฅผ ํ•˜๊ฒŒ๋˜๋ฉด, ์ˆ˜์ •์ž…๋ ฅ์„ ํ•ด๋„ ์„œ๋ฒ„๋ฅผ restarting ํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ๊ณ ์นจ์œผ๋กœ ๋ณ€ํ™”๋ฅผ ํ™•์ธ
"""
if __name__ == "__main__":
    app.run_server(debug=True,host = '127.0.0.1')

 

๐Ÿ’› ์‹คํ–‰

 

 

4๏ธโƒฃ ๋Œ€์‹œ๋ณด๋“œ์— Style ์ž…ํžˆ๊ธฐ

๐Ÿ’š (1) ํƒœ๊ทธ์— ์ง์ ‘ style

  • H1 ํƒœ๊ทธ์— ํฐํŠธ ์‚ฌ์ด์ฆˆ์™€ ์ƒ‰์ƒ ์ถ”๊ฐ€
html.H1(
    children="Temp Analytics",
    style={"fontSize": "48px", "color": "blue"},
),

  • but, css ํŒŒ์ผ์— ๋‹ค์‹œ ๊ด€๋ฆฌ ํ•ด์ฃผ์ž! ์œ„ ์ฝ”๋“œ์—์„œ style ๋‹ค์‹œ ์ง€์šฐ๊ณ  assets ํด๋” ํ•˜์œ„์— style.css ์ถ”๊ฐ€

  • H1 ํƒœ๊ทธ์—๋Š” ํด๋ž˜์Šค ์ถ”๊ฐ€
html.H1(
    children="Temp Analytics",
    className="header_title",
),
  • className์— ํ•ด๋‹นํ•˜๋Š” css ์ฝ”๋“œ๋ฅผ style.css ์— ์ถ”๊ฐ€
.header_title {
    font-size: 48px;
    color: red;
  }

 

๐Ÿ’š (2) ๋กœ๊ณ  ์ถ”๊ฐ€

 

๐Ÿ’š (3) External Style Sheet

  • ์™ธ๋ถ€์—์„œ css ํŒŒ์ผ ๊ฐ–๊ณ ์˜ค๊ธฐ
# step 3. Dash Class
external_stylesheets = [
    {
        "href": "https://fonts.googleapis.com/css2?"
        "family=Lato:wght@400;700&display=swap",
        "rel": "stylesheet",
    },
]

# ์™ธ๋ถ€์—์„œ css sheet ๊ฐ–๊ณ ์˜ค๊ธฐ
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)        # app = dash.Dash(__name__)
app.title = "Avocado Analytics: Understand Your Avocados!"

 

 

๐Ÿ’š (4) Header Layout ์ปค์Šคํ…€ํ™”

  • header ํ™”๋ฉด๊ณผ ๊ทธ๋ž˜ํ”„ ๊ตฌ์„ฑํ•˜๋Š” ํ™”๋ฉด์„ div ํƒœ๊ทธ๋กœ ๊ตฌ๋ถ„ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ
  • className์„ ๊ฐ ํƒœ๊ทธ๋งˆ๋‹ค ์ž…๋ ฅํ•˜๊ธฐ
# step 4. HTML
app.layout = html.Div(
    children=[
        html.Div(
            children=[
                html.P(children="๐Ÿฅ‘", className="header-emoji"),
                html.H1(
                    children="Avocado Analytics", className="header-title"
                ),
                html.P(
                    children="Analyze the behavior of avocado prices"
                    " and the number of avocados sold in the US"
                    " between 2015 and 2018",
                    className="header-description",
                ),
            ],
            className="header",
        ),
        html.Div(
            children=[
                html.Div(
                    children=dcc.Graph(
                        id="price-chart",
                        config={"displayModeBar": False},
                        figure={
                            "data": [
                                {
                                    "x": data["Date"],
                                    "y": data["AveragePrice"],
                                    "type": "lines",
                                    "hovertemplate": "$%{y:.2f}"
                                                     "<extra></extra>",
                                },
                            ],
                            "layout": {
                                "title": {
                                    "text": "Average Price of Avocados",
                                    "x": 0.05,
                                    "xanchor": "left",
                                },
                                "xaxis": {"fixedrange": True},
                                "yaxis": {
                                    "tickprefix": "$",
                                    "fixedrange": True,
                                },
                                "colorway": ["#17B897"],
                            },
                        },
                    ),
                    className="card",
                ),
                html.Div(
                    children=dcc.Graph(
                        id="volume-chart",
                        config={"displayModeBar": False},
                        figure={
                            "data": [
                                {
                                    "x": data["Date"],
                                    "y": data["Total Volume"],
                                    "type": "lines",
                                },
                            ],
                            "layout": {
                                "title": {
                                    "text": "Avocados Sold",
                                    "x": 0.05,
                                    "xanchor": "left",
                                },
                                "xaxis": {"fixedrange": True},
                                "yaxis": {"fixedrange": True},
                                "colorway": ["#E12D39"],
                            },
                        },
                    ),
                    className="card",
                ),
            ],
            className="wrapper",
        ),
    ]
)
  •  cssํŒŒ์ผ
body {
    font-family: "Lato", sans-serif;
    margin: 0;
    background-color: #F7F7F7;
}

.header {
    background-color: #222222;
    height: 256px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.header-emoji {
    font-size: 48px;
    margin: 0 auto;
    text-align: center;
}

.header-title {
    color: #FFFFFF;
    font-size: 48px;
    font-weight: bold;
    text-align: center;
    margin: 0 auto;
}

.header-description {
    color: #CFCFCF;
    margin: 4px auto;
    text-align: center;
    max-width: 384px;
}

.wrapper {
    margin-right: auto;
    margin-left: auto;
    max-width: 1024px;
    padding-right: 10px;
    padding-left: 10px;
    margin-top: 32px;
}

.card {
    margin-bottom: 24px;
    box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.18);
}

.header_emoji {
    font-size: 48px;
    margin: 0 auto;
    text-align: center;
}

.header_title {
    color: #FFFFFF;
    font-size: 48px;
    font-weight: bold;
    text-align: center;
    margin: 0 auto;
}

.header_description {
    color: #CFCFCF;
    margin: 4px auto;
    text-align: center;
    max-width: 384px;
}

.header {
    background-color: #222222;
    height: 256px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

 

๐Ÿ’š ๊ฒฐ๊ณผ

 

 

5๏ธโƒฃ ๋Œ€์‹œ๋ณด๋“œ์— Interactive ๊ตฌํ˜„

  • ๋‚ ์งœ๋ฅผ ์ง€์ •ํ•˜์—ฌ ๊ทธ๋ž˜ํ”„๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜๋Š” ์—†์„๊นŒ?
  • ์ง€์—ญ์„ ์„ ํƒํ•  ๋•Œ๋งˆ๋‹ค, ๋ผ์ธ ๊ทธ๋ž˜ํ”„๊ฐ€ ๋ณ€๋™์‹œํ‚ฌ ์ˆ˜๋Š” ์—†์„๊นŒ?

 

๐Ÿงก (1) ๋ฉ”๋‰ด ๊ตฌ์„ฑํ•˜๊ธฐ

  • ๋ฐ์ดํ„ฐ๋ถ€ํ„ฐ ํ™•์ธ
# step 2. Data Import
data = pd.read_csv("coding/220927/avocado.csv", index_col=0)
data = data.query("type == 'conventional' and region == 'Albany'")      # type = conventional ๊ณผ, region = Albany ๋งŒ ์ถ”์ถœํ•˜๋Š” ํ–‰์„ ์ถ”์ถœ
data["Date"] = pd.to_datetime(data["Date"], format="%Y-%m-%d")          
data.sort_values("Date", inplace=True)                                  # ๋‚ ์งœ์˜ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ์ฝ”๋“œ
print(data.info())

  • 3๊ฐ€์ง€ ์ปฌ๋Ÿผ์„ ๋ฉ”๋‰ด๋กœ ํ™œ์šฉ
    • Region
    • Type of avocado
    • Date range
  • type, region ํ™•์ธ
# step 2. Data Import
data = pd.read_csv("coding/220927/avocado.csv", index_col=0)
#data = data.query("type == 'conventional' and region == 'Albany'")      # type = conventional ๊ณผ, region = Albany ๋งŒ ์ถ”์ถœํ•˜๋Š” ํ–‰์„ ์ถ”์ถœ
data["Date"] = pd.to_datetime(data["Date"], format="%Y-%m-%d")          
data.sort_values("Date", inplace=True)                                  # ๋‚ ์งœ์˜ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ์ฝ”๋“œ
#print(data.info())
print(data[['region', 'type', 'Date']].head())

 

 

 

  • html layout ๋ณ€๊ฒฝ
# step 4. HTML
app.layout = html.Div(
    children=[
        html.Div(
            children=[
                html.P(children="๐Ÿฅ‘", className="header-emoji"),
                html.H1(
                    children="Avocado Analytics", className="header-title"
                ),
                html.P(
                    children="Analyze the behavior of avocado prices"
                    " and the number of avocados sold in the US"
                    " between 2015 and 2018",
                    className="header-description",
                ),
            ],
            className="header",
        ),
        html.Div(
            children=[
                html.Div(
                    children=[
                        html.Div(children="Region", className="menu-title"),
                        dcc.Dropdown(
                            id="region-filter",
                            options=[
                                {"label": region, "value": region}
                                for region in np.sort(data.region.unique())
                            ],
                            value="Albany",
                            clearable=False,
                            className="dropdown",
                        ),
                    ]
                ),
                html.Div(
                    children=[
                        html.Div(children="Type", className="menu-title"),
                        dcc.Dropdown(
                            id="type-filter",
                            options=[
                                {"label": avocado_type, "value": avocado_type}
                                for avocado_type in data.type.unique()
                            ],
                            value="organic",
                            clearable=False,
                            searchable=False,
                            className="dropdown",
                        ),
                    ],
                ),
                html.Div(
                    children=[
                        html.Div(
                            children="Date Range",
                            className="menu-title"
                            ),
                        dcc.DatePickerRange(
                            id="date-range",
                            min_date_allowed=data.Date.min().date(),
                            max_date_allowed=data.Date.max().date(),
                            start_date=data.Date.min().date(),
                            end_date=data.Date.max().date(),
                        ),
                    ]
                ),
            ],
            className="menu",
        ),
        html.Div(
            children=[
                html.Div(
                    children=dcc.Graph(
                        id="price-chart", config={"displayModeBar": False},
                    ),
                    className="card",
                ),
                html.Div(
                    children=dcc.Graph(
                        id="volume-chart", config={"displayModeBar": False},
                    ),
                    className="card",
                ),
            ],
            className="wrapper",
        ),
    ]
)

๐Ÿ‘€ ์ฐธ๊ณ 

  • id : Dropdown ๋ฉ”๋‰ด์˜ ID๋ฅผ ๊ตฌ์„ฑ. ํ•ด๋‹น ID๋Š” ํ–ฅํ›„ Callback์„ ์ •์˜ํ•  ๋•Œ, ๊ฐ™์ด ํ™œ์šฉ๋จ
  • optinos : Dropdown ๋ฉ”๋‰ด๊ฐ€ ์ตœ์ดˆ ์„ ํƒ์ด ๋  ๋•Œ, ๊ฐ’(labesl ๋˜๋Š” values)์„ ๋ณด์—ฌ์คŒ
  • value : Default๋œ ๊ฐ’์„ ๋ณด์—ฌ์คŒ
  • className : style.css ์ด ์ ์šฉ๋˜๋Š” ์˜์—ญ
html.Div(
    children=[
        html.Div(children="Region", className="menu-title"),
        dcc.Dropdown(
            id="region-filter",
            options=[
                {"label": region, "value": region}
                for region in np.sort(data.region.unique())

 

  • style.css ํŒŒ์ผ์— ๋ฉ”๋‰ด ๊ตฌ์„ฑ ์ถ”๊ฐ€
.menu {
    height: 112px;
    max-width: 1024px;
    display: flex;
    justify-content: space-evenly;
    padding-top: 32px;
    margin: 0px auto 0 auto;
    background-color: #FFFFFF;
    box-shadow: 0 4px 6px 0 rgba(0, 0, 0, 0.18);
}

.menu-title {
    margin-bottom: 6px;
    font-weight: bold;
    color: #079A82;
}

.Select-control {
    width: 256px;
    height: 48px;
}

.Select--single > .Select-control .Select-value, .Select-placeholder {
    line-height: 48px;
}

.Select--multi .Select-value-label {
    line-height: 32px;
}.

 

๐Ÿงก ๊ฒฐ๊ณผ

 

  • ๊ทธ๋Ÿฐ๋ฐ ๋ฉ”๋‰ด๋ž‘ ๊ทธ๋ž˜ํ”„๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์•ˆ๋‚˜์˜จ๋‹ค
    • Reactive Programming
      • ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ˜์‘์„ ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ
        • ex) ๋‹ค๋ฅธ ์œ ์ €๊ฐ€ ํŽ˜์ด์Šค๋ถ์— ‘์ข‹์•„์š”’ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ•ด๋‹น ํฌ์ŠคํŠธ๋ฅผ ๋ณด๊ณ  ์žˆ๋Š” ์‚ฌ์šฉ์ž๋Š” ์ƒˆ๋กœ๊ณ ์นจ ํ•  ๊ฒƒ ์—†์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ‘์ข‹์•„์š”’์˜ ๊ฐœ์ˆ˜๊ฐ€ ์˜ฌ๋ผ๊ฐ€๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.
        • ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ๋Š” ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค๊ณ  ๋งํ•จ
    • Callbacks
      • Reactive Programming์˜ ํ•ต์‹ฌ์ด์ž, ๋ณธ Tutorial์˜ ํ•ต์‹ฌ.
      • Callback ํ•จ์ˆ˜๋ž€, ๊ฐœ๋ฐœ์ž๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ๋งŒ ํ•  ๋ฟ, ์‹ค์ œ ์‚ฌ์ดํŠธ ๋ฐฉ๋ฌธ์ž๊ฐ€ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋ฉด, ํŠน์ • ์‹œ์ ์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™” ์‹œํ‚ค๋Š” ๊ฒƒ

 

 

๐Ÿงก ์ฝœ๋ฐฑ ๋ฐ Reactive ์‹คํ–‰ํ•˜๋Š” ์ฝ”๋“œ ์ถ”๊ฐ€

from dash.dependencies import Output, Input
@app.callback(
    [Output("price-chart", "figure"), Output("volume-chart", "figure")],
    [
        Input("region-filter", "value"),
        Input("type-filter", "value"),
        Input("date-range", "start_date"),
        Input("date-range", "end_date"),
    ],
)
def update_charts(region, avocado_type, start_date, end_date):
    mask = (
        (data.region == region)
        & (data.type == avocado_type)
        & (data.Date >= start_date)
        & (data.Date <= end_date)
    )
    filtered_data = data.loc[mask, :]
    price_chart_figure = {
        "data": [
            {
                "x": filtered_data["Date"],
                "y": filtered_data["AveragePrice"],
                "type": "lines",
                "hovertemplate": "$%{y:.2f}<extra></extra>",
            },
        ],
        "layout": {
            "title": {
                "text": "Average Price of Avocados",
                "x": 0.05,
                "xanchor": "left",
            },
            "xaxis": {"fixedrange": True},
            "yaxis": {"tickprefix": "$", "fixedrange": True},
            "colorway": ["#17B897"],
        },
    }

    volume_chart_figure = {
        "data": [
            {
                "x": filtered_data["Date"],
                "y": filtered_data["Total Volume"],
                "type": "lines",
            },
        ],
        "layout": {
            "title": {"text": "Avocados Sold", "x": 0.05, "xanchor": "left"},
            "xaxis": {"fixedrange": True},
            "yaxis": {"fixedrange": True},
            "colorway": ["#E12D39"],
        },
    }
    return price_chart_figure, volume_chart_figure

 

๐Ÿงก ๊ฒฐ๊ณผ

 

 

 

 

 

 

 

์‹ค์‹œ๊ฐ„์œผ๋กœ ์›€์งใ…‡ใ…ฃ๋Š” ๊ทธ๋ž˜ํ”„๋„ ํ•ด๋ณด๊ณ  ์‹ถ๋‹ค

728x90
๋ฐ˜์‘ํ˜•
Comments