Dash 第61回(DashCanvas 選択情報をテーブル表示)

選択情報をテーブル表示

キャンバス上で長方形の選択をした箇所をテーブルに表示してみます。

長方形で選択した範囲をparse_jsonstring_rectangleで取得し(67行目)、そのデータをDataFrameに変換してDataTableコンポーネントに設定・表示します。(68~70行目)

また、線の色を選択できるラジオボタンも作成しています。(23~27行目、51~56行目)

[ソースコード]

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
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import pandas as pd
from dash.dependencies import Input, Output
from dash_canvas import DashCanvas
from dash_canvas.utils import array_to_data_url, parse_jsonstring_rectangle
from skimage import io

filename = array_to_data_url(io.imread('cherry.png'))
pen_color = ['black', 'lime', 'red', 'blue', 'yellow']
columns = ['width', 'height', 'left', 'top']

app = dash.Dash(__name__) # Dashインスタンスを生成

# レイアウト作成
app.layout = html.Div(
[
html.Div(
[
# 線の色を選択するラジオボタン
dcc.RadioItems(
id='color1',
options=[{'value':c, 'label':c} for c in pen_color],
value='lime'
),
DashCanvas(
id='image1',
image_content=filename,
width=400,
lineWidth=5,
goButtonTitle='to_table'
)
],
),
html.Div(
[
# 選択した長方形の範囲を表示するテーブル
dash_table.DataTable(
id='table1',
columns=[{'name':i, 'id':i} for i in columns],
export_format='csv'
)
]
)
]
)

# 線の色を更新するコールバック
@app.callback(
Output('image1', 'lineColor'),
Input('color1', 'value')
)
def update_color(selected_color):
return selected_color

# 選択した長方形の範囲をテーブルに表示するコールバック
@app.callback(
Output('table1', 'data'),
Input('image1', 'json_data')
)
def showLine(json_data):
if not json_data:
raise dash.exceptions.PreventUpdate
else:
data = parse_jsonstring_rectangle(json_data)
if len(data):
df = pd.DataFrame(data, columns=columns)
return df.to_dict('records')

if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

[ブラウザで表示]

キャンバス上をいくつか長方形で選択をした後に、to_tableボタンを押すと選択情報がテーブルに表示されます。

またExportボタンを押すと選択情報をCSVファイルに出力することができます。

Dash 第60回(DashCanvas 画像表示)

DashCanvas 画像表示

キャンバスに画像を表示します。

画像を表示する手順は、以下の通りです。

  1. imread関数を使って、画像をnumpy.ndarray型に変換する。(7行目)
  2. array_to_data_url関数を使って、文字列に変換する。(7行目)
  3. 文字列に変換した画像データを、DashCanvasの引数 image_contentに設定し、キャンバスに画像を表示する。(13行目)

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import dash
from dash_canvas import DashCanvas
from dash_canvas.utils import array_to_data_url
from skimage import io

# 画像を変数に渡す
data = array_to_data_url(io.imread('cherry.png'))
app = dash.Dash(__name__) # Dashインスタンスを生成

# レイアウト作成
app.layout = DashCanvas(
id='image1',
image_content=data, # コンポーネントへ画像を設定
width=500, # キャンバスの横幅
lineWidth=12, # アノテーションの横幅
goButtonTitle='Test', # Saveボタンのタイトル
lineColor='lime', # アノテーションの線の色
hide_buttons=['zoom', 'pan', 'line'] # ボタンを非表示
)

if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

キャンバスの横幅や、編集ツールの設定も行っています。(14~18行目)

[ブラウザで表示]

キャンバスに画像が表示され、編集ツールを使って画像を編集することができました。

Dash 第59回(DashCanvasクラスの属性)

DashCanvasクラスの属性

DashCanvasクラスの属性を一覧に表します。

属性 データ型 内容
id 文字列 コンポーネントのIDを設定。
image_content 文字列 PNGまたはJPEGフォーマットの画像データ文字列を設定。
array_to_data_url関数を用いて生成する。
zoom 数値 画像の拡大を設定。
width 数値 キャンバスの横幅を設定。
height 数値 キャンバスの高さを設定。
scale 数値 キャンバスの横幅と画像の横幅の縮尺比を設定。
tool ‘pencil’
‘pen’
‘circle’
‘rectangle’
‘select’
‘line’
描画ツールの初期値を設定。
lineWidth 数値 ペンシルモード時の線幅を設定。
lineColor 文字列 ペンシルモード時の線の色、色名、RGB、RGBAを指定可能。
goButtonTitle 文字列 Saveボタンのタイトルを設定。
filename 文字列 ロードする画像ファイル名(URL文字列)を設定。
trigger 数値 Saveボタンが押された回数データを保持。
json_data 文字列 アノテーションの内容を保持。
hide_buttons ‘pencil’,’zoom’などのリスト型 非表示にする描画ツールを指定。

Dash 第58回(DashCanvas アノテーション表示)

アノテーション表示

json_data属性を使って、キャンバスのアノテーションの内容を表示するアプリケーションを作成します。

レイアウトとしてDashCanvasコンポ―ネントの下に、アノテーションの内容を表示するDivコンポーネントを配置します。(10行目)

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import json
import dash
import dash_html_components as html
from dash.dependencies import Input, Output
from dash_canvas import DashCanvas

app = dash.Dash(__name__) # Dashインスタンスを生成

# レイアウト作成
app.layout = html.Div([DashCanvas(id='canvas1'), html.Div(id='div1')])

@app.callback(
# 入力項目にID'canvas1'のjson_data属性を設定
Output('div1', 'children'),
Input('canvas1', 'json_data')
)
def show_json(json_data):
if json_data: # json_data属性にデータが存在するかどうか
return json.dumps(json_data) # json_dataを文字列にして返す
else:
raise dash.exceptions.PreventUpdate # コールバックを更新しない

if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

コールバック関数では、出力項目をDivコンポーネントのchildren属性、入力項目をDashCanvasコンポーネントのjson_data属性としています。(14~15行目)

json_data属性にデータがある場合、json_data属性の値を返し、データがない場合はコールバックの更新を行いません。(18~21行目)

[ブラウザで表示]

キャンバスに線を描画し、Saveボタンをクリックするとアノテーションの内容が表示されることを確認できます。

Dash 第57回(DashCanvas)

DashCanvasコンポーネントは、画像編集ツールをもつキャンバスです。

キャンバス上に画像を表示し、アノテーションを用いて画像処理をすることができます。

インストール

DashCanvasコンポーネントを使うためには、下記のコマンドを実行しインストールを行います。

[コマンド]

1
pip install dash-canvas

DashCanvasサンプルコード

デフォルト設定のDashCanvasコンポーネントを作成するコードは下記の通りです。

[ソースコード]

1
2
3
4
5
6
7
import dash
from dash_canvas import DashCanvas

app = dash.Dash(__name__) # Dashインスタンスを生成
app.layout = DashCanvas()
if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

[ブラウザで表示]

線や枠を描画したり、移動・拡大・縮小などができます。

編集ツール右端のSaveボタンでは、画像の保存ではなくDashCanvasコンポーネントのjson_data属性の更新を行います。

json_data属性は描き込みツールを使って描いたアノテーションのデータをもつ属性で、データはJSON形式で保存されます、

Dash 第56回(テーブルデータを地図に表示)

テーブルデータを地図に表示

テーブル上の位置データを地図上に表示します。

地図を表示するためにmapboxよりアクセストークンを取得しておく必要があります。(12行目で設定)

[ソースコード]

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
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import pandas as pd
import plotly.express as px
from dash.dependencies import Input, Output

df = pd.read_csv('401307compatibleformatshelter.csv', encoding='cp932')

# mapboxのアクセストークンを設定
px.set_mapbox_access_token('<<mapboxで取得したトークン>>')

app = dash.Dash(__name__) # Dashインスタンスを生成

app.layout = html.Div(
[
html.Div(
[
html.H2('避難所マップ'),
dash_table.DataTable(
id='table1',
# セルサイズの設定
style_cell={
'textAliign':'center', # テキストを中央寄せ
'maxWidth':'80px', # 最大横幅
'minWidth':'80px', # 最小横幅
'whiteSpace':'normal' # 文字を折り返して表示
},
fixed_rows={'headers':True}, # 縦スクロール時にヘッダーを固定
columns=[{'name':col, 'id':col} for col in df.columns],
data=df.to_dict('records')
)
]
),
dcc.Graph(id='map1')
]
)

@app.callback(
Output('map1', 'figure'),
Input('table1', 'columns'),
Input('table1', 'derived_virtual_data')
)
def update_map(columns, rows):
df = pd.DataFrame(rows, columns=[c['name'] for c in columns])
return px.scatter_mapbox(
df,
lat='緯度',
lon='経度',
zoom=10,
hover_data=['名称', '名称かな表記', '住所表記']
)

if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

コールバック関数には、テーブルの引数columnsderived_virtual_dataを入力としています。

derived_virtual_dataは、テーブルの全ページデータです。

update_map関数では、列名と全データからDataFrameを作成し、そのDataFrameをscatter_mapbox関数に設定し、地図上に散布図を描画したfigureを返しています。(46~53行目)

[ブラウザで表示]

テーブルの位置データが地図上に散布図として描画されていることを確認できました。

Dash 第55回(テーブルのソートとエクスポート)

テーブルのソートとエクスポート

DataTableコンポーネントには、属性を設定しソートエクスポートを可能にすることができます。

  • sort_action属性
    ‘native’を設定すると、項目名に上下マークが表示されソート可能になる。(28行目)
    ‘custom’を設定すると、コールバックを使ったカスタマイズが可能になる。
  • sort_mode属性
    ‘single’を設定すると、1つの列のソートが可能になる。
    ‘multi’を設定すると、複数列のソートが可能になる。(29行目)
  • export_format属性
    ‘csv’を設定すると、テーブルに表示されているデータをCSVファイルでダウンロードできるようになる。(30行目)

[ソースコード]

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
import dash
import dash_html_components as html
import dash_table
import pandas as pd

df = pd.read_csv('401307compatibleformatshelter.csv', encoding='cp932')

app = dash.Dash(__name__) # Dashインスタンスを生成

app.layout = html.Div(
[
dash_table.DataTable(
# セルサイズの設定
style_cell={
'textAliign':'center', # テキストを中央寄せ
'maxWidth':'80px', # 最大横幅
'minWidth':'80px', # 最小横幅
'whiteSpace':'normal' # 文字を折り返して表示
},
fixed_rows={'headers':True}, # 縦スクロール時にヘッダーを固定
style_table={'minWidth':'100%'}, # テーブル全幅表示
columns=[{'name':col, 'id':col} for col in df.columns],
data=df.to_dict('records'),
editable=True,
filter_action="native",
row_deletable=True,
row_selectable='multi',
sort_action='native', # 列のソートを可能に
sort_mode='multi', # 複数列のソートを可能に
export_format='csv' # エクスポートの設定
)
]
)

if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

[ブラウザで表示]

項目名の左に表示されている上下マークをクリックすると列をソートすることができます。

また、テーブルの左上に表示されているexportボタンをクリックすると、表示されているデータをCSVファイルでダウンロードできます。

Dash 第54回(テーブルの行削除と行選択)

テーブルの行削除と行選択

DataTableコンポーネントには、属性を設定し行の削除行の選択を可能にすることができます。

row_deletable属性Trueを設定すると行の先頭に×マークが表示され行の削除ができるようになります。(26行目)

またrow_selectable属性‘single’を指定すると行を1つ選択することができるようになり、‘multi’を指定すると行を複数選択することができようになります。(27行目)

[ソースコード]

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
import dash
import dash_html_components as html
import dash_table
import pandas as pd

df = pd.read_csv('401307compatibleformatshelter.csv', encoding='cp932')

app = dash.Dash(__name__) # Dashインスタンスを生成

app.layout = html.Div(
[
dash_table.DataTable(
# セルサイズの設定
style_cell={
'textAliign':'center', # テキストを中央寄せ
'maxWidth':'80px', # 最大横幅
'minWidth':'80px', # 最小横幅
'whiteSpace':'normal' # 文字を折り返して表示
},
fixed_rows={'headers':True}, # 縦スクロール時にヘッダーを固定
style_table={'minWidth':'100%'}, # テーブル全幅表示
columns=[{'name':col, 'id':col} for col in df.columns],
data=df.to_dict('records'),
editable=True,
filter_action="native",
row_deletable=True, # 行の消去を可能に
row_selectable='multi' # 複数行の選択を可能に
)
]
)

if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

[ブラウザで表示]

行先頭の×マークをクリックすると行が削除され、チェックボックスをクリックすると複数行を選択することができます。

Dash 第53回(テーブルの編集とフィルター)

テーブルの編集とフィルター

DataTableコンポーネントには、属性を設定しセルの編集機能フィルター機能を追加することができます。

editable属性Trueを設定すると全てのセルが編集可能になります。(24行目)

またfilter_action属性‘native’を設定すると、フィルタリングができるようになります。(25行目)

[ソースコード]

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
import dash
import dash_html_components as html
import dash_table
import pandas as pd

df = pd.read_csv('401307compatibleformatshelter.csv', encoding='cp932')

app = dash.Dash(__name__) # Dashインスタンスを生成

app.layout = html.Div(
[
dash_table.DataTable(
# セルサイズの設定
style_cell={
'textAliign':'center', # テキストを中央寄せ
'maxWidth':'80px', # 最大横幅
'minWidth':'80px', # 最小横幅
'whiteSpace':'normal' # 文字を折り返して表示
},
fixed_rows={'headers':True}, # 縦スクロール時にヘッダーを固定
style_table={'minWidth':'100%'}, # テーブル全幅表示
columns=[{'name':col, 'id':col} for col in df.columns],
data=df.to_dict('records'),
editable=True, # セルを編集可能に
filter_action="native" # フィルタリングを可能に
)
]
)

if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

[ブラウザで表示]

選択したセルに対して、編集ができるようになっています。

またフィルタリングエリアに入力すると、その入力値を含んだデータだけが表示されます。

Dash 第52回(テーブルの表示幅変更とヘッダー固定表示)

テーブルの表示幅変更とヘッダー固定表示

前回記事ではCSVファイルを読み込んでテーブルに表示しました。

今回はそのテーブルのスタイルを設定します。

まずセルの横幅を均等にするため、‘maxWidth’‘minWidth’に同じ値を設定します。(16~17行目)

次にセルの内容を折り返すために、‘whiteSpace’‘normal’を設定します。(18行目)

行ヘッダーを固定するため引数 fixed_rowsに、キーが‘headers’、値がTrueである辞書データを設定します。(20行目)

最後に、引数 style_table100%を設定し、テーブルに縦スクロールと横スクロールが表示されるようにします。(21行目)

[ソースコード]

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
import dash
import dash_html_components as html
import dash_table
import pandas as pd

df = pd.read_csv('401307compatibleformatshelter.csv', encoding='cp932')

app = dash.Dash(__name__) # Dashインスタンスを生成

app.layout = html.Div(
[
dash_table.DataTable(
# セルサイズの設定
style_cell={
'textAliign':'center', # テキストを中央寄せ
'maxWidth':'80px', # 最大横幅
'minWidth':'80px', # 最小横幅
'whiteSpace':'normal' # 文字を折り返して表示
},
fixed_rows={'headers':True}, # 縦スクロール時にヘッダーを固定
style_table={'minWidth':'100%'}, # テーブル全幅表示
columns=[{'name':col, 'id':col} for col in df.columns],
data=df.to_dict('records')
)
]
)

if __name__ == '__main__':
app.run_server(debug=True) # アプリケーションを起動

[ブラウザで表示]

セルの横幅が均等で、セルの内容が折り返して表示されています。

また、縦横にスクロールが表示されており、縦にスクロールしてもヘッダーが固定して表示されることを確認できます。