顯示具有 Dash 標籤的文章。 顯示所有文章
顯示具有 Dash 標籤的文章。 顯示所有文章

2023年7月15日 星期六

用Python Dash來設計展示用的儀錶板(ChatGPT版本)

 Python Dash 是一個用於建立交互式網頁應用程式的 Python 函式庫,它基於 Flask、React 和 Plotly 等技術,提供了一個簡單且高效的方式來創建數據驅動的儀表板和可視化應用。以下是 Python Dash 的一些特點和功能:

  1. 快速構建:Python Dash 具有簡單的語法和豐富的組件庫,可以快速構建具有交互性的網頁應用程式。你可以使用 Python 語言來定義應用程式的外觀和行為,並使用 Dash 的組件庫來創建互動元素。
  2. 數據驅動:Python Dash 支持數據驅動的編程模型,你可以將數據和圖表直接與應用程式的組件綁定。當數據更新時,應用程式的視覺化元素會自動更新,從而實現動態和即時的數據展示。
  3. 可視化:Python Dash 集成了 Plotly 函式庫,可以輕鬆地創建各種互動式圖表和可視化效果。你可以使用 Plotly 的功能來創建折線圖、柱狀圖、散點圖、熱圖等各種類型的圖表。靈活的配置:
  4. Python Dash 具有靈活的配置和佈局選項,你可以自由設計應用程式的外觀和佈局。你可以使用 CSS 樣式表進行自定義,並使用組件庫中的佈局元素來創建多欄、多行的應用程式佈局。
  5. 服務器端渲染:Python Dash 使用 Flask 作為後端框架,並使用 React 作為前端框架。這種結合使得應用程式在服務器端進行渲染,提供了更好的性能和較快的響應時間。

Python Dash 是一個強大的工具,可用於快速開發數據驅動的儀表板和可視化應用。它提供了豐富的組件庫和可視化功能,並與 Python 生態系統緊密集成。你可以使用 Python Dash 在簡單的 Python 語法下構建強大的互動性網頁應用程式。

範例一:折線圖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import dash
from dash import dcc
from dash import html

# 創建 Dash 應用程式
app = dash.Dash(__name__)

# 模擬數據
x_data = [1, 2, 3, 4, 5]
y_data = [10, 15, 7, 12, 8]

# 創建佈局
app.layout = html.Div(
    children=[
        html.H1('折線圖範例'),
        dcc.Graph(
            figure={
                'data': [
                    {'x': x_data, 'y': y_data, 'type': 'line', 'name': '折線圖'}
                ],
                'layout': {
                    'title': '數據趨勢',
                    'xaxis': {'title': 'X 軸'},
                    'yaxis': {'title': 'Y 軸'}
                }
            }
        )
    ]
)

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

請將上面程式碼存成XXX.py,然後再用命令列,執行Python XXX.py。

執行結果:

範例二:柱狀圖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import dash
from dash import dcc
from dash import html

# 創建 Dash 應用程式
app = dash.Dash(__name__)

# 模擬數據
x_data = ['A', 'B', 'C', 'D']
y_data = [10, 15, 7, 12]

# 創建佈局
app.layout = html.Div(
    children=[
        html.H1('柱狀圖範例'),
        dcc.Graph(
            figure={
                'data': [
                    {'x': x_data, 'y': y_data, 'type': 'bar', 'name': '柱狀圖'}
                ],
                'layout': {
                    'title': '數據分布',
                    'xaxis': {'title': '類別'},
                    'yaxis': {'title': '數量'}
                }
            }
        )
    ]
)

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

執行結果:

範例三:散點圖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import dash
from dash import dcc
from dash import html

# 創建 Dash 應用程式
app = dash.Dash(__name__)

# 模擬數據
x_data = [1, 2, 3, 4, 5]
y_data = [10, 15, 7, 12, 8]

# 創建佈局
app.layout = html.Div(
    children=[
        html.H1('散點圖範例'),
        dcc.Graph(
            figure={
                'data': [
                    {'x': x_data, 'y': y_data, 'mode': 'markers', 'name': '散點圖'}
                ],
                'layout': {
                    'title': '數據分布',
                    'xaxis': {'title': 'X 軸'},
                    'yaxis': {'title': 'Y 軸'}
                }
            }
        )
    ]
)

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

執行結果:

範例四:熱圖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import dash
from dash import dcc
from dash import html

# 創建 Dash 應用程式
app = dash.Dash(__name__)

# 模擬數據
x_data = [1, 2, 3, 4, 5]
y_data = [12, 19, 3, 24, 8]
z_data = [25, 3, 18, 13, 8]
 

# 創建佈局
app.layout = html.Div(
    children=[
        html.H1('熱圖範例'),
        dcc.Graph(
            figure={
                'data': [
                    {
                        'x': x_data,
                        'y': y_data,
                        'z': z_data,
                        'type': 'heatmap',
                        'colorscale': 'Viridis'
                    }
                ],
                'layout': {
                    'title': '數據熱度',
                    'xaxis': {'title': 'X 軸'},
                    'yaxis': {'title': 'Y 軸'}
                }
            }
        )
    ]
)

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

執行結果:

範例五:數據驅動

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output

# 創建 Dash 應用程式
app = dash.Dash(__name__)

# 模擬數據
x_data = [1, 2, 3, 4, 5]
y_data = [10, 15, 7, 12, 8]

# 創建佈局
app.layout = html.Div(
    children=[
        html.H1('數據驅動的範例'),
        dcc.Dropdown(
            id='dropdown',
            options=[
                {'label': '選項 A', 'value': 'A'},
                {'label': '選項 B', 'value': 'B'},
                {'label': '選項 C', 'value': 'C'}
            ],
            value='A'
        ),
        dcc.Graph(id='graph')
    ]
)

@app.callback(
    Output('graph', 'figure'),
    Input('dropdown', 'value')
)
def update_graph(selected_option):
    if selected_option == 'A':
        data = [
            {'x': x_data, 'y': y_data, 'type': 'line', 'name': '數據 A'}
        ]
    elif selected_option == 'B':
        data = [
            {'x': x_data, 'y': [y*2 for y in y_data], 'type': 'line', 'name': '數據 B'}
        ]
    else:
        data = [
            {'x': x_data, 'y': [y**2 for y in y_data], 'type': 'line', 'name': '數據 C'}
        ]
    
    return {
        'data': data,
        'layout': {
            'title': '動態更新圖表',
            'xaxis': {'title': 'X 軸'},
            'yaxis': {'title': 'Y 軸'}
        }
    }

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

執行結果:
選項A:

選項B:

選項C:

範例六:使用CSS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import dash
from dash import dcc
from dash import html

app = dash.Dash(__name__)

app.layout = html.Div(
    children=[
        html.H1('使用 CSS 的範例', style={'color': 'blue', 'text-align': 'center'}),
        dcc.Graph(
            figure={
                'data': [
                    {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': '數據'}
                ],
                'layout': {
                    'title': '圖表標題',
                    'xaxis': {'title': 'X 軸'},
                    'yaxis': {'title': 'Y 軸'}
                }
            },
            style={'width': '50%', 'margin': '0 auto'}
        )
    ],
    style={'background-color': '#f2f2f2', 'padding': '20px'}
)

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

執行結果:


2020年3月22日 星期日

使用Python,Dash和Plotly等技術將COVID-19案例數據視覺化

上圖是執行程式後,查詢台灣COVID-19案例數據視覺化的結果,此程式是使用PythonDash和Plotly等技術,以Flask網站來呈現視覺化的結果。

參考文章:Visualise COVID-19 case data using Python, Dash and Plotly
程式網址:https://github.com/ploner/coronavirus-py


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
from dash.dependencies import Input, Output
import pandas as pd

baseURL = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/"

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

tickFont = {'size':12, 'color':"rgb(30,30,30)", 'family':"Courier New, monospace"}

def loadData(fileName, columnName): 
    data = pd.read_csv(baseURL + fileName) \
             .drop(['Lat', 'Long'], axis=1) \
             .melt(id_vars=['Province/State', 'Country/Region'], var_name='date', value_name=columnName) \
             .fillna('<all>')
    data['date'] = data['date'].astype('datetime64[ns]')
    return data

allData = loadData("time_series_19-covid-Confirmed.csv", "CumConfirmed") \
    .merge(loadData("time_series_19-covid-Deaths.csv", "CumDeaths")) \
    .merge(loadData("time_series_19-covid-Recovered.csv", "CumRecovered"))

countries = allData['Country/Region'].unique()
countries.sort()

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

app.layout = html.Div(
    style={ 'font-family':"Courier New, monospace" },
    children=[
    html.H1('Case History of the Coronavirus (COVID-19)'),
    html.Div(className="row", children=[
        html.Div(className="four columns", children=[
            html.H5('Country'),
            dcc.Dropdown(
                id='country',
                options=[{'label':c, 'value':c} for c in countries],
                value='Italy'
            )
        ]),
        html.Div(className="four columns", children=[
            html.H5('State / Province'),
            dcc.Dropdown(
                id='state'
            )
        ]),
        html.Div(className="four columns", children=[
            html.H5('Selected Metrics'),
            dcc.Checklist(
                id='metrics',
                options=[{'label':m, 'value':m} for m in ['Confirmed', 'Deaths', 'Recovered']],
                value=['Confirmed', 'Deaths']
            )
        ])
    ]),
    dcc.Graph(
        id="plot_new_metrics",
        config={ 'displayModeBar': False }
    ),
    dcc.Graph(
        id="plot_cum_metrics",
        config={ 'displayModeBar': False }
    )
])

@app.callback(
    [Output('state', 'options'), Output('state', 'value')],
    [Input('country', 'value')]
)
def update_states(country):
    states = list(allData.loc[allData['Country/Region'] == country]['Province/State'].unique())
    states.insert(0, '<all>')
    states.sort()
    state_options = [{'label':s, 'value':s} for s in states]
    state_value = state_options[0]['value']
    return state_options, state_value

def nonreactive_data(country, state):
    data = allData.loc[allData['Country/Region'] == country]
    if state == '<all>':
        data = data.drop('Province/State', axis=1).groupby("date").sum().reset_index()
    else:
        data = data.loc[data['Province/State'] == state]
    newCases = data.select_dtypes(include='int64').diff().fillna(0)
    newCases.columns = [column.replace('Cum', 'New') for column in newCases.columns]
    data = data.join(newCases)
    data['dateStr'] = data['date'].dt.strftime('%b %d, %Y')
    return data

def barchart(data, metrics, prefix="", yaxisTitle=""):
    figure = go.Figure(data=[
        go.Bar( 
            name=metric, x=data.date, y=data[prefix + metric],
            marker_line_color='rgb(0,0,0)', marker_line_width=1,
            marker_color={ 'Deaths':'rgb(200,30,30)', 'Recovered':'rgb(30,200,30)', 'Confirmed':'rgb(100,140,240)'}[metric]
        ) for metric in metrics
    ])
    figure.update_layout( 
              barmode='group', legend=dict(x=.05, y=0.95, font={'size':15}, bgcolor='rgba(240,240,240,0.5)'), 
              plot_bgcolor='#FFFFFF', font=tickFont) \
          .update_xaxes( 
              title="", tickangle=-90, type='category', showgrid=True, gridcolor='#DDDDDD', 
              tickfont=tickFont, ticktext=data.dateStr, tickvals=data.date) \
          .update_yaxes(
              title=yaxisTitle, showgrid=True, gridcolor='#DDDDDD')
    return figure

@app.callback(
    Output('plot_new_metrics', 'figure'), 
    [Input('country', 'value'), Input('state', 'value'), Input('metrics', 'value')]
)
def update_plot_new_metrics(country, state, metrics):
    data = nonreactive_data(country, state)
    return barchart(data, metrics, prefix="New", yaxisTitle="New Cases per Day")

@app.callback(
    Output('plot_cum_metrics', 'figure'), 
    [Input('country', 'value'), Input('state', 'value'), Input('metrics', 'value')]
)
def update_plot_cum_metrics(country, state, metrics):
    data = nonreactive_data(country, state)
    return barchart(data, metrics, prefix="Cum", yaxisTitle="Cumulated Cases")

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

程式解說:
程式第1-7行滙入所需要套件
程式第8行定義一個baseURL,數據位於約翰霍普金斯大學系統科學與工程中心(JHU / CSSE)的服務器上,讓我們可以按國家和地區下載冠狀病毒的病例數據。
程式第10行指定引用CSS的網址。
程式第12行設定字型等CSS樣式。
程式第14到20行定義函數loadData處理下載和一些基本轉換。
程式第22到24行載入案例數據含確診、死亡、康復等人數。
程式第26到27行過濾重複資料以及排序。
程式第29行建立儀錶板物件。
程式第31行到67行建立網頁的佈局
程式第69行到79行是回呼函式處理選擇國家時能列出各省的資訊。
程式第81行到91行是依照區域和省份等資訊列出COVID-19的資料。
程式第93行到109行是將資訊轉成條狀圖。
程式第111行到125行是回呼函式反應網站送來的資訊。
程式第127行到128行是主程式