[{"data":1,"prerenderedAt":565},["ShallowReactive",2],{"news-item-\u002Fja\u002Fnews\u002Ftruc-quan-hoa-du-lieu-bang-python-dash":3},{"id":4,"title":5,"body":6,"category":552,"created by":553,"date":554,"description":555,"extension":556,"meta":557,"navigation":558,"path":559,"sections":560,"seo":561,"stem":562,"thumbnail":563,"__hash__":564},"content_ja\u002Fja\u002Fnews\u002Ftruc-quan-hoa-du-lieu-bang-python-dash.md","Python Dashによるデータ可視化",{"type":7,"value":8,"toc":547},"minimark",[9,14,18,22,26,29,32,35,38,41,44,48,51,54,57,68,77,85,89,97,102,106,109,112,115,118,122,125,128,134,137,143,152,162,165,170,177,180,194,197,205,208,214,218,221,227,230,235,238,241,246,252,255,261,264,270,274,277,280,286,289,295,298,304,310,316,323,330,335,338,346,350,353,359,365,370,376,379,382,393,397,400,409,412,415,420,423,429,432,438,442,445,451,454,462,465,471,474,482,485,491,494,500,509,513,516,520,523,526,532,535,541],[10,11,13],"h1",{"id":12},"dash-とは","Dash とは",[15,16,17],"p",{},"DashはMITライセンスで公開されているオープンソースのライブラリです。このライブラリは、Plotly.js、ReactJs上に構築されています。Dashは、カスタム化されるUI（ユーザーインターフェイス）を備えたデータ可視化アプリを構築するのに理想的です。Dashは非常に簡単なので10分未満でUIをソースコードにバインドできます。DashはWebブラウザーにレンダリングされるため、クロスプラットフォーム及びモバイルデバイスで実行できます。",[10,19,21],{"id":20},"dash利用のご案内","Dash利用のご案内",[23,24,25],"h3",{"id":25},"設定方法",[15,27,28],{},"環境：端末でPython 3 がすでにインストールされています。",[15,30,31],{},"ターミナルでは、Dashをインストールするために以下のコマンドを実行します。",[15,33,34],{},"pip install dash",[15,36,37],{},"上記のコマンドの実行により、Dashに加えてpipはチャート描画ライブラリ( Plotly.py)もインストールします。",[15,39,40],{},"最後に、次のコマンドを実行することによりPandasライブラリをインストールします。",[15,42,43],{},"pip install pandas",[10,45,47],{"id":46},"pandasについて","Pandasについて",[15,49,50],{},"PandasはオープンソースでBSDライセンスで公開されています。Pandasは、Pythonプログラミング言語用に高性能で使いやすいデータ構造とデータ分析ツールを提供します。",[15,52,53],{},"Pandasは、DataFrame及びSeriesという２つの主要なデータ構造を提供します。DataFrameは文字、整数、浮動小数点値、カテゴリカルデータといった様々なタイプのデータを列に格納できる2次元のデータ構造です。DataFrameの１行や１列の情報もSeriesに対応します。",[15,55,56],{},"列形式でデータを格納するには次の一般的な規則が３つあります。",[58,59,60],"ul",{},[61,62,63,67],"li",{},[64,65,66],"strong",{},"長い形式のデータには","、観測ごとに1つの行があり、変数ごとに1つの列があります。これは、多変量データ、つまり次元が2より大きいデータの保存および表示に適しています。",[69,70],"img",{"className":71,"alt":74,"src":75,"style":76},[72,73],"block","mx-auto","","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31142643\u002Flong_form_2.png","width: 50%;",[58,78,79],{},[61,80,81,84],{},[64,82,83],{},"ワイドフォームデータには","、最初の変数の1つの値ごとに1つの行があり、2番目の変数の値ごとに1つの列があります。これは、2次元データの保存および表示に適しています。",[69,86],{"className":87,"alt":74,"src":88,"style":76},[72,73],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31142738\u002Fwide_form_2.png",[58,90,91],{},[61,92,93,96],{},[64,94,95],{},"混合形式のデータは","、長い形式と広い形式のデータのハイブリッドです。",[69,98],{"className":99,"alt":74,"src":100,"style":101},[72,73],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31142805\u002Fmixed_form.png","width: 70%;",[10,103,105],{"id":104},"dashのレイアウトについて","Dashのレイアウトについて",[15,107,108],{},"Dashアプリはレイアウト及びコールバックという２つの主要部分で構成されています。レイアウトは、アプリがどのように表示されるかを示します。コールバックは、アプリのインタラクティブ性を示します。",[15,110,111],{},"「レイアウト」は各コンポーネントを組むツリーです。",[15,113,114],{},"DashはDashHTMLコンポーネント、Dashコアコンポーネント、Dashデータテーブル、Dash DAQ、DashBootstrapコンポーネントなどの多種類のコンポーネントを提供します。",[15,116,117],{},"この記事では、DashHTMLコンポーネント及びDashコアコンポーネントについて説明します。",[10,119,121],{"id":120},"dashhtmlコンポーネント","DashHTMLコンポーネント",[15,123,124],{},"レイアウトのHTMLタグを定義するために用いられるHTMLコンポーネントを提供する関数です。",[15,126,127],{},"Dash HTMLコンポーネントの使用を開始するには、次のように.pyファイルにインポートする必要があります。",[15,129,130],{},[131,132,133],"code",{},"from dash import html",[15,135,136],{},"例:",[15,138,139],{},[140,141,142],"em",{},"html_demo.py",[144,145,150],"pre",{"className":146,"code":148,"language":149},[147],"language-text","import dash\nfrom dash import html\n\napp = dash.Dash(__name__)\n\napp.layout = html.Div(children=[\n   html.H1(children='Hello Dash'),\n])\n\nif __name__ == '__main__':\n   app.run_server(debug=True)\n","text",[131,151,148],{"__ignoreMap":74},[15,153,154,157,158,161],{},[131,155,156],{},"「html.H1(children='Hello Dash')」`","はブラウザで",[131,159,160],{},"「\u003Ch1>Hello Dash\u003C\u002Fh1>」`","を生成します。",[15,163,164],{},"CHTMLタグと同様に「style」プロパティを使用してhtml_componentのスタイルを変更することもできます。",[15,166,167],{},[131,168,169],{},"例：html.H1('Hello Dash', style={'textAlign': 'center', 'color': '#7FDBFF'})",[15,171,172,173,176],{},"上記のコードは",[131,174,175],{},"「\u003Ch1 style=\"text-align: center; color: #7FDBFF\">Hello Dash\u003C\u002Fh1>」","として表示されます。",[15,178,179],{},"DashHTMLコンポーネントとHTML属性の間にはいくつかの重要な相違があります。",[58,181,182,185,188,191],{},[61,183,184],{},"HTMLの「style」というプロパティはセミコロンで区切られた文字列です。Dashでは、dictionary（辞書）を提供する必要があります。",[61,186,187],{},"dictionaryのキー名はキャメルケース形式になります。 したがって「text-align」の代わりに、Dashで「textAlign」になります。",[61,189,190],{},"HTMLの「class」というプロパティは、Dashで「className」になります。",[61,192,193],{},"HTMLタグの子要素は「children」キーワードを使用した引数を介して指定されます。",[15,195,196],{},"また、スタイルを直接使用する代わりに、レイアウトにスタイルを定義するためにCSSファイルを利用することもできます。 詳細は下記のURLをご参照ください。",[15,198,199],{},[200,201,202],"a",{"href":202,"rel":203},"https:\u002F\u002Fdash.plotly.com\u002Fexternal-resources",[204],"nofollow",[15,206,207],{},"利用可能なすべてのコンポーネントはHTML Components Galleryで確認できます。",[15,209,210],{},[200,211,212],{"href":212,"rel":213},"https:\u002F\u002Fdash.plotly.com\u002Fdash-html-components",[204],[10,215,217],{"id":216},"dashコアコンポーネント","Dashコアコンポーネント",[15,219,220],{},"ドロップダウン、チェックボックス、ラジオ、グラフといった高レベルの各コンポーネントのセットを含めるものです。 利用可能なすべてのコンポーネントはDash Core Components Galleryで確認できます。",[15,222,223],{},[200,224,225],{"href":225,"rel":226},"https:\u002F\u002Fdash.plotly.com\u002Fdash-core-components",[204],[15,228,229],{},"Dashコアコンポーネントの使用を開始するには、次のように.pyファイルをインポートする必要があります。",[15,231,232],{},[131,233,234],{},"from dash import dcc",[15,236,237],{},"各コアコンポーネントの中に「Graph」はデータ可視化にとって重要なコンポーネントです。「Graph」は、Plotly.jsというJavaScriptオープンソースグラフ作成ライブラリを使用してブラウザへデータの可視化をレンダリングするものです。Plotly.jsは35種類以上のチャートタイプをサポートし、ベクター品質のSVG及び高パフォーマンスのWebGL形式でチャットをレンダリングさせます。注意すべき点としてはPlotly.jsはブラウザへのレンダリングにのみ使用されています（これがDashで行われる）が、コーディングする時には、Javascriptで直接コーディングせずにPlotly.pyライブラリを使用します（これがDashをインストールする時に提供される）。",[15,239,240],{},"Graphコンポーネントの使用方法については、csvデータを折れ線グラフとしてブラウザへレンダリングする例を見てみましょう。",[15,242,243],{},[140,244,245],{},"csv\u002Fgraph_sample.csv",[144,247,250],{"className":248,"code":249,"language":149},[147],"DateTime,DATA 1,DATA 2,DATA 3,DATA 4\n20211220 101010.000,30,100,124,197\n20211220 101010.010,40,110,134,65\n20211220 101010.020,50,140,214,149\n20211220 101010.030,60,150,169,-98\n20211220 101010.040,70,160,204,-173\n20211220 101010.050,80,170,164,-108\n20211220 101010.060,90,180,148,150\n20211220 101010.070,100,190,180,92\n20211220 101010.080,110,200,268,94\n20211220 101010.090,120,210,164,-139\n20211220 101010.100,130,220,254,-132\n",[131,251,249],{"__ignoreMap":74},[15,253,254],{},"まず、csvファイルを読み込むためにpandasを使用する必要があります。",[144,256,259],{"className":257,"code":258,"language":149},[147],"df = pd.read_csv('csv\u002Fgraph_sample.csv')\n",[131,260,258],{"__ignoreMap":74},[15,262,263],{},"変数「df」をコンソールに印刷して、その構造を確認します。",[144,265,268],{"className":266,"code":267,"language":149},[147],"print(df)\n",[131,269,267],{"__ignoreMap":74},[69,271],{"className":272,"alt":74,"src":273,"style":101},[72,73],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31144341\u002Fexample_wide_form.png",[15,275,276],{},"こちらの形式は覚えていますか？ そうです。先ほど上記で言及されていたPandasの広い形式のデータです！",[15,278,279],{},"次は、DateTime列のデータをstringからdatetimeに変換して、グラフにデータの日時が正しく表示されるようにします。",[144,281,284],{"className":282,"code":283,"language":149},[147],"df['DateTime'] = pd.to_datetime(df['DateTime'], format='%Y%m%d %H:%M:%S.%f')\n",[131,285,283],{"__ignoreMap":74},[15,287,288],{},"そして、plotly expressでline figureを作成します。",[144,290,293],{"className":291,"code":292,"language":149},[147],"line_fig = px.line(df, x='DateTime', y=['DATA 1', 'DATA 2', 'DATA 3', 'DATA 4'])\n",[131,294,292],{"__ignoreMap":74},[15,296,297],{},"Graphコンポーネントにfigureを引き渡します。",[144,299,302],{"className":300,"code":301,"language":149},[147],"app.layout = html.Div(children=[\n    dcc.Graph(id='graph', figure=line_fig)\n])\n",[131,303,301],{"__ignoreMap":74},[15,305,306,307],{},"完全なコードは下記のようです。 ",[140,308,309],{},"graph_demo.py",[144,311,314],{"className":312,"code":313,"language":149},[147],"import dash\nimport pandas as pd\nimport plotly.express as px\nfrom dash import dcc\nfrom dash import html\n\napp = dash.Dash(__name__)\n\ndf = pd.read_csv('csv\u002Fgraph_sample.csv')\nprint(df)\ndf['DateTime'] = pd.to_datetime(df['DateTime'], format='%Y%m%d %H:%M:%S.%f')\n\nline_fig = px.line(df, x='DateTime', y=['DATA 1', 'DATA 2', 'DATA 3', 'DATA 4'])\n\napp.layout = html.Div(children=[\n   dcc.Graph(id='graph', figure=line_fig)\n])\n\nif __name__ == '__main__':\n   app.run_server(debug=True)\n",[131,315,313],{"__ignoreMap":74},[15,317,318,319,322],{},"ターミナルでは次のコマンドを実行します。 ",[131,320,321],{},"python graph_demo.py"," 最後に、",[15,324,325,329],{},[200,326,327],{"href":327,"rel":328},"http:\u002F\u002F127.0.0.1:8050\u002F",[204]," にアクセスして結果を確認します。",[69,331],{"className":332,"alt":74,"src":333,"style":334},[72,73],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31144923\u002Fexample_graph-1024x373.png","width: 100%;",[15,336,337],{},"上記の例の中には、",[58,339,340,343],{},[61,341,342],{},"Pandasライブラリは、入力データを処理するために用いられます（csvを読み取り、DateTime列のデータをstringからdatetimeに変換する）。",[61,344,345],{},"Plotly.pyライブラリにあるPlotly Expressは、出力Graphのグラフタイプ（折れ線図、散布図）、x軸、y軸などを指定する役割を担います。",[10,347,349],{"id":348},"dashコールバック","Dashコールバック",[15,351,352],{},"コールバック関数は別のコンポーネント（出力）の一部のプロパティを更新するために、入力コンポーネントのプロパティが変更されるたびにDashによって自動的に呼び出されるものです。",[15,354,355,356],{},"コールバックをより深く理解するには、dcc.DatePickerRangeコンポーネントからの入力を使用して日付でデータをフィルターする例を見てみましょう。 ",[140,357,358],{},"csv\u002Fcallbacks_sample.csv",[144,360,363],{"className":361,"code":362,"language":149},[147],"DateTime,DATA 1,DATA 2,DATA 3,DATA 4\n20211219 101010.010,10,200,178,90\n20211219 111010.020,20,150,134,25\n20211219 121010.030,5,130,210,11\n20211219 131010.040,15,110,100,-97\n20211219 141010.050,60,150,143,-17\n20211219 151010.060,30,140,132,30\n20211219 161010.070,20,180,167,45\n20211219 171010.080,16,120,240,123\n20211219 181010.090,75,190,153,40\n20211219 191010.100,90,250,162,-10\n20211220 001010.000,68,142,156,1\n20211220 011010.010,40,110,134,65\n20211220 021010.020,50,140,214,149\n20211220 031010.030,60,150,169,-98\n20211220 041010.040,70,160,204,-173\n20211220 051010.050,80,170,164,-108\n20211220 061010.060,90,180,148,150\n20211220 071010.070,100,190,180,92\n20211220 081010.080,110,200,268,94\n20211220 091010.090,120,210,164,-139\n20211220 101010.100,130,220,254,-132\n20211221 001010.000,10,90,142,30\n20211221 011010.010,30,100,162,55\n20211221 021010.020,80,120,180,20\n20211221 031010.030,70,110,176,-10\n20211221 041010.040,50,130,194,-90\n20211221 051010.050,60,140,202,-120\n20211221 061010.060,90,150,164,100\n20211221 071010.070,120,160,197,132\n20211221 081010.080,110,170,186,40\n20211221 091010.090,130,210,182,-130\n20211221 101010.100,120,230,210,-100\n",[131,364,362],{"__ignoreMap":74},[15,366,367],{},[140,368,369],{},"callbacks_demo.py",[144,371,374],{"className":372,"code":373,"language":149},[147],"from datetime import datetime, timedelta\n\nimport dash\nimport pandas as pd\nimport plotly.express as px\nfrom dash import dcc, Output, Input\nfrom dash import html\n\napp = dash.Dash(__name__)\n\ndf = pd.read_csv('csv\u002Fcallbacks_sample.csv')\ndf['DateTime'] = pd.to_datetime(df['DateTime'], format='%Y%m%d %H:%M:%S.%f')\n\ninit_start_date = df['DateTime'].min().strftime('%Y-%m-%d')\ninit_end_date = df['DateTime'].max().strftime('%Y-%m-%d')\n\napp.layout = html.Div(children=[\n   dcc.DatePickerRange(\n       id='date-picker-range',\n       start_date=init_start_date,\n       end_date=init_end_date,\n       minimum_nights=0,\n       display_format='YYYY\u002FMM\u002FDD'\n   ),\n   dcc.Graph(id='scatter-graph'),\n])\n\n@app.callback(\n   Output('scatter-graph', 'figure'),\n   Input('date-picker-range', 'start_date'),\n   Input('date-picker-range', 'end_date')\n)\ndef update_figure(start_date, end_date):\n   if start_date is not None and end_date is not None:\n       start_date = datetime.fromisoformat(start_date)\n       end_date = datetime.fromisoformat(end_date) + timedelta(days=1)\n       filtered_df = df[(start_date \u003C= df['DateTime']) & (df['DateTime'] \u003C= end_date)]\n       scatter_fig = px.scatter(filtered_df, x='DateTime', y=['DATA 1', 'DATA 2', 'DATA 3', 'DATA 4'])\n\n       return scatter_fig\n\nif __name__ == '__main__':\n   app.run_server(debug=True)\n",[131,375,373],{"__ignoreMap":74},[15,377,378],{},"Dashでは、アプリの入力と出力は単に特定のコンポーネントのプロパティにすぎません。この例では、入力は「date-picker-range」IDを持つコンポーネントの「start_date」及び「end_date」プロパティであり、出力は「scatter-graph」IDを持つコンポーネントの「figure」プロパティになります。",[15,380,381],{},"@callbackデコレーターが宣言された関数は、入力プロパティが変更されるたびに自動的に呼び出されます。 Dashは、入力プロパティに新しく入力された値を入力引数としてコールバック関数に提供し（上記の例でupdate_figure関数は「start_date」、「end_date」という２つの引数を持つ）、関数の戻り値を出力コンポーネントのプロパティに更新します。（上記の例でupdate_figure関数はscatter_figを返却）",[15,383,384,385,388,389,392],{},"ターミナルで",[131,386,387],{},"python callbacks_demo.py","コマンドを実行し、",[200,390,327],{"href":327,"rel":391},[204],"にアクセスして結果を確認します。",[69,394],{"className":395,"alt":74,"src":396,"style":334},[72,73],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31145606\u002Fcallback_demo_pic1-1024x381.png",[15,398,399],{},"end_dateを変更した後の結果",[15,401,402,406],{},[69,403],{"className":404,"alt":74,"src":405,"style":334},[72,73],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31145648\u002Fcallbacks_demo_pic2-1024x387.png",[407,408],"br",{},[10,410,411],{"id":411},"最適化及び機能追加",[15,413,414],{},"この部分ではコールバックのコードを使用してそのコードに最適化して機能を追加します。",[416,417,419],"h4",{"id":418},"データ数nを読み取ります","データ数nを読み取ります。",[15,421,422],{},"現在、入力データの数を4個に固定に設定しています。",[144,424,427],{"className":425,"code":426,"language":149},[147],"scatter_fig = px.scatter(filtered_df, x='DateTime', y=['DATA 1', 'DATA 2', 'DATA 3', 'DATA 4'])\n",[131,428,426],{"__ignoreMap":74},[15,430,431],{},"もし入力データが「DATA 1, DATA 2,..., DATA n」どんな量でもあるとすると、上記のコードでは4個のデータしか読み取って表示できません。 データ数nを読み取ってグラフへ表示するには、コードを少し修正する必要があります。",[144,433,436],{"className":434,"code":435,"language":149},[147],"# get first columns name for x-axis\nx_col_name = df.columns[0]\n# get list column name except first column for y-axis\ny_col_name_list = df.columns[1:]\nfiltered_df = df[(start_date \u003C= df[x_col_name]) & (df[x_col_name] \u003C= end_date)]\nscatter_fig = px.scatter(filtered_df, x=x_col_name, y=y_col_name_list)\n",[131,437,435],{"__ignoreMap":74},[416,439,441],{"id":440},"csvのヘッダーからconfigを読み取ります","CSVのヘッダーからconfigを読み取ります。",[15,443,444],{},"CSVのヘッダーを次のように考えます。",[144,446,449],{"className":447,"code":448,"language":149},[147],"DateTime(yyyyMMdd HH:mm:ss.fff),DATA 1(minFilter=20;maxFilter=100),DATA 2(maxFilter=140),DATA 3,DATA 4,DATA 5\n",[131,450,448],{"__ignoreMap":74},[15,452,453],{},"上記のヘッダーからconfigを読み取る機能を追加します。",[58,455,456,459],{},[61,457,458],{},"DateTime列のconfigを読み取って日時の形式を設定します（現在、コードで固定に設定されている）。",[61,460,461],{},"DATA列のmaxFilter、minFilterのconfigを読み取りそのDATA列のminFilterより小さくmaxFilterより大きい値のデータを除外します。",[15,463,464],{},"まず、共通関数を含めるutils.pyファイルを追加します。",[144,466,469],{"className":467,"code":468,"language":149},[147],"import re\n\n_format_convertor = (\n   ('yyyy', '%Y'), ('yyy', '%Y'), ('yy', '%y'), ('y', '%y'),\n   ('MMMM', '%B'), ('MMM', '%b'), ('MM', '%m'), ('M', '%m'),\n   ('dddd', '%A'), ('ddd', '%a'), ('dd', '%d'), ('d', '%d'),\n   ('HH', '%H'), ('H', '%H'), ('hh', '%I'), ('h', '%I'),\n   ('mm', '%M'), ('m', '%M'),\n   ('ss', '%S'), ('s', '%S'),\n   ('tt', '%p'), ('t', '%p'),\n   ('fff', '%f'),\n   ('zzz', '%z'), ('zz', '%z'), ('z', '%z'),\n)\n\ndef convert_py_datetime_format(in_format):\n   out_format = ''\n   while in_format:\n       if in_format[0] == \"'\":\n           apos = in_format.find(\"'\", 1)\n           if apos == -1:\n               apos = len(in_format)\n           out_format += in_format[1:apos].replace('%', '%%')\n           in_format = in_format[apos + 1:]\n       elif in_format[0] == '\\\\':\n           out_format += in_format[1:2].replace('%', '%%')\n           in_format = in_format[2:]\n       else:\n           for intok, outtok in _format_convertor:\n               if in_format.startswith(intok):\n                   out_format += outtok\n                   in_format = in_format[len(intok):]\n                   break\n           else:\n               out_format += in_format[0].replace('%', '%%')\n               in_format = in_format[1:]\n   return out_format\n\ndef extract_csv_col_config(col_name: str):\n   try:\n       found = re.search('\\\\((.*)\\\\)', col_name)\n       col_name = col_name.replace(found.group(0), '')\n       config_string = found.group(1)\n       config_list = config_string.split(';')\n       configs = []\n       for config in config_list:\n           key_value_list = config.split('=')\n           key = key_value_list[0]\n           value = key_value_list[1] if len(key_value_list) > 1 else None\n           configs.append((key, value))\n   except AttributeError:\n       configs = []\n   return col_name, configs\n",[131,470,468],{"__ignoreMap":74},[15,472,473],{},"上記のコードには、",[58,475,476,479],{},[61,477,478],{},"convert_py_datetime_format関数は、yyyyMMdd HH:mm:ss.fffの形式をPython形式に変換するために用いられます。",[61,480,481],{},"extract_csv_col_config関数は、configを含む列名を受け取り、config文字列が除外された列名及びその列のconfigを含むarrayを返します。例えば、DATA 1(minFilter=20;maxFilter=100)は、DATA 1とarray [(minFilter, 20), (maxFilter, 100)]を返します。",[15,483,484],{},"次に、process_csv_variable関数をapp.pyに追加します。",[144,486,489],{"className":487,"code":488,"language":149},[147],"from datetime import datetime, timedelta\n\nimport dash\nimport numpy as np\nimport pandas as pd\nimport plotly.express as px\nfrom dash import dcc, Output, Input\nfrom dash import html\n\nfrom utils import extract_csv_col_config, convert_py_datetime_format\n\ndef process_csv_variable(df_param):\n   # process x-axis csv variable\n   old_x_col_name = df_param.columns[0]\n   new_x_col_name, configs = extract_csv_col_config(old_x_col_name)\n   datetime_format = configs[0][0]\n   df_param = df_param.rename(columns={old_x_col_name: new_x_col_name})\n   df_param[new_x_col_name] = pd.to_datetime(df_param[new_x_col_name],\n                                             format=convert_py_datetime_format(datetime_format))\n   # process y-axis csv variable\n   y_col_name_list = df_param.columns[1:]\n   for old_y_col_name in y_col_name_list:\n       new_y_col_name, configs = extract_csv_col_config(old_y_col_name)\n       df_param = df_param.rename(columns={old_y_col_name: new_y_col_name})\n       for config, value in configs:\n           if config == 'minFilter':\n               df_param.loc[df_param[new_y_col_name] \u003C int(value), new_y_col_name] = np.nan\n           elif config == 'maxFilter':\n               df_param.loc[df_param[new_y_col_name] > int(value), new_y_col_name] = np.nan\n   return df_param\n\napp = dash.Dash(__name__)\n\napp.layout = html.Div(id='container', children=[\n   dcc.DatePickerRange(\n       id='date-picker-range',\n       minimum_nights=0,\n       display_format='YYYY\u002FMM\u002FDD'\n   ),\n   dcc.Graph(id='scatter-graph'),\n])\n\n@app.callback(\n   Output('date-picker-range', 'start_date'),\n   Output('date-picker-range', 'end_date'),\n   Input('container', 'id')\n)\ndef update_date_picker(id):\n   df = pd.read_csv('csv\u002Fapp_sample.csv')\n   df = process_csv_variable(df)\n   x_col_name = df.columns[0]\n\n   init_start_date = df[x_col_name].min().strftime('%Y-%m-%d')\n   init_end_date = df[x_col_name].max().strftime('%Y-%m-%d')\n   return init_start_date, init_end_date\n\n@app.callback(\n   Output('scatter-graph', 'figure'),\n   Input('date-picker-range', 'start_date'),\n   Input('date-picker-range', 'end_date')\n)\ndef update_figure(start_date, end_date):\n   df = pd.read_csv('csv\u002Fapp_sample.csv')\n   df = process_csv_variable(df)\n   if start_date is not None and end_date is not None:\n       start_date = datetime.fromisoformat(start_date)\n       end_date = datetime.fromisoformat(end_date) + timedelta(days=1)\n       # get first columns name for x-axis\n       x_col_name = df.columns[0]\n       # get list column name except first column for y-axis\n       y_col_name_list = df.columns[1:]\n       filtered_df = df[(start_date \u003C= df[x_col_name]) & (df[x_col_name] \u003C= end_date)]\n       scatter_fig = px.scatter(filtered_df, x=x_col_name, y=y_col_name_list)\n\n       return scatter_fig\n\nif __name__ == '__main__':\n   app.run_server(debug=True)\n",[131,490,488],{"__ignoreMap":74},[15,492,493],{},"process_csv_variable関数はDataFrameを受け取り、列名からconfigを読み取りconfigによるデータを処理してからDataFrameを返します。 今、csv\u002Fapp_sample.csvファイルを追加してテストします。",[144,495,498],{"className":496,"code":497,"language":149},[147],"DateTime(yyyyMMdd HH:mm:ss.fff),DATA 1(minFilter=20;maxFilter=100),DATA 2(maxFilter=140),DATA 3,DATA 4,DATA 5\n20211219 101010.010,10,200,178,90,110\n20211219 111010.020,20,150,134,25,120\n20211219 121010.030,5,130,210,11,90\n20211219 131010.040,15,110,100,-97,80\n20211219 141010.050,60,150,143,-17,130\n20211219 151010.060,30,140,132,30,140\n20211219 161010.070,20,180,167,45,150\n20211219 171010.080,16,120,240,123,160\n20211219 181010.090,75,190,153,40,150\n20211219 191010.100,90,250,162,-10,170\n20211220 001010.000,68,142,156,1,180\n20211220 011010.010,40,110,134,65,130\n20211220 021010.020,50,140,214,149,190\n20211220 031010.030,60,150,169,-98,200\n20211220 041010.040,70,160,204,-173,190\n20211220 051010.050,80,170,164,-108,180\n20211220 061010.060,90,180,148,150,170\n20211220 071010.070,100,190,180,92,150\n20211220 081010.080,110,200,268,94,160\n20211220 091010.090,120,210,164,-139,140\n20211220 101010.100,130,220,254,-132,130\n20211221 001010.000,10,90,142,30,150\n20211221 011010.010,30,100,162,55,160\n20211221 021010.020,80,120,180,20,170\n20211221 031010.030,70,110,176,-10,110\n20211221 041010.040,50,130,194,-90,90\n20211221 051010.050,60,140,202,-120,80\n20211221 061010.060,90,150,164,100,70\n20211221 071010.070,120,160,197,132,60\n20211221 081010.080,110,170,186,40,50\n20211221 091010.090,130,210,182,-130,40\n20211221 101010.100,120,230,210,-100,30\n",[131,499,497],{"__ignoreMap":74},[15,501,502,503,388,506,392],{},"ターミナルでは",[131,504,505],{},"python app.py",[200,507,327],{"href":327,"rel":508},[204],[69,510],{"className":511,"alt":74,"src":512,"style":334},[72,73],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31150435\u002Fapp_demo1-1024x371.png",[15,514,515],{},"結果を確認しやすくするために、他のデータを非表示にしDATA1のみを表示します。",[69,517],{"className":518,"alt":74,"src":519,"style":334},[72,73],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31150508\u002Fapp_demo2-1024x373.png",[15,521,522],{},"20より小さい値及び100より大きい値のデータが除外されていることがわかります。",[10,524,525],{"id":525},"ソースコード",[15,527,528],{},[200,529,530],{"href":530,"rel":531},"https:\u002F\u002Fgitlab.com\u002Fbwv-hp\u002Fpython-dash-sample",[204],[10,533,534],{"id":534},"参照元",[15,536,537],{},[200,538,539],{"href":539,"rel":540},"https:\u002F\u002Fdash.plotly.com\u002F",[204],[15,542,543],{},[200,544,545],{"href":545,"rel":546},"https:\u002F\u002Fpandas.pydata.org\u002Fdocs\u002F",[204],{"title":74,"searchDepth":548,"depth":548,"links":549},2,[550],{"id":25,"depth":551,"text":25},3,"tech talk","NGHIA NGUYEN TRUNG","2022-01-25","Dash とは DashはMITライセンスで公開されているオープンソースのライブラリです。このライブラリは、Plotly.js、ReactJs上に構築されています。Dashは、カスタム化されるUI（ユーザーインターフェイス）を備えたデータ可視化アプリを構築するのに理想的です。Dashは非常に簡単なので10分未満でUIをソースコードにバインドできます。DashはWebブラウザーにレンダリングされるため、クロスプラットフォーム及びモバイルデバイスで実行できます。","md",{},true,"\u002Fja\u002Fnews\u002Ftruc-quan-hoa-du-lieu-bang-python-dash",null,{"title":5,"description":555},"ja\u002Fnews\u002Ftruc-quan-hoa-du-lieu-bang-python-dash","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2026\u002F06\u002F04082100\u002Fpython_dash.png","KOZbKPiAbJgjWK7sqchDBWRFmPNGluGwb2MhVtbBK3Q",1782263094613]