[{"data":1,"prerenderedAt":716},["ShallowReactive",2],{"news-item-\u002Fnews\u002Ftruc-quan-hoa-du-lieu-bang-python-dash":3},{"id":4,"title":5,"body":6,"category":703,"created by":704,"date":705,"description":706,"extension":707,"meta":708,"navigation":709,"path":710,"sections":711,"seo":712,"stem":713,"thumbnail":714,"__hash__":715},"content_en\u002Fnews\u002Ftruc-quan-hoa-du-lieu-bang-python-dash.md","Data Visualization with Python Dash",{"type":7,"value":8,"toc":688},"minimark",[9,14,18,22,27,30,41,44,50,54,57,60,63,74,82,90,94,102,107,111,123,134,137,140,145,148,154,157,162,168,178,185,191,197,200,233,242,249,253,260,266,276,282,287,293,296,302,305,311,315,318,321,327,330,336,339,345,348,353,359,362,368,376,381,384,392,396,399,402,407,413,418,424,446,470,480,484,489,493,497,500,504,507,513,516,519,525,529,532,538,541,562,569,575,578,604,614,620,626,633,639,648,652,655,659,662,666,672,676,682],[10,11,13],"h1",{"id":12},"introduction-to-dash","Introduction to Dash",[15,16,17],"p",{},"Dash is an open source library released under the permissive MIT license. Written on top of Plotly.js and React.js, Dash is ideal for building and deploying data apps with customized user interfaces. Dash is simple enough that you can bind a user interface to your code in less than 10 minutes. Dash apps are rendered in the web browser, so it can run on cross-platform and also mobile devices.",[10,19,21],{"id":20},"dash-tutorial","Dash tutorial",[23,24,26],"h2",{"id":25},"dash-installation","Dash Installation",[15,28,29],{},"Requires the computer to have Python 3 installed. In the terminal run the following command to install Dash:",[31,32,37],"pre",{"className":33,"code":35,"language":36},[34],"language-text","pip install dash\n","text",[38,39,35],"code",{"__ignoreMap":40},"",[15,42,43],{},"With the above command, in addition to dash, pip will also install the graphing support library that is Plotly. And finally we need to install the Pandas library with the command:",[31,45,48],{"className":46,"code":47,"language":36},[34],"pip install pandas\n",[38,49,47],{"__ignoreMap":40},[23,51,53],{"id":52},"about-pandas","About Pandas",[15,55,56],{},"Pandas is an open source library released under the permissive BSD license. Pandas provides high-performance, easy-to-use data structures and data analysis tools for the Python programming language.",[15,58,59],{},"Pandas provides two main data structures, DataFrame and Series. A DataFrame is a 2D data structure that can store data of different types (including characters, integers, floating point values, categorical data and more) in columns. Each column in a DataFrame is a Series.",[15,61,62],{},"There are three common conventions for storing column-oriented data:",[64,65,66],"ul",{},[67,68,69,73],"li",{},[70,71,72],"strong",{},"Long-form data"," has one row per observation, and one column per variable. This is suitable for storing and displaying multivariate data i.e. with dimension greater than 2.",[75,76],"img",{"className":77,"alt":40,"src":80,"style":81},[78,79],"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%;",[64,83,84],{},[67,85,86,89],{},[70,87,88],{},"Wide-form data"," has one row per value of one of the first variable, and one column per value of the second variable. This is suitable for storing and displaying 2D data.",[75,91],{"className":92,"alt":40,"src":93,"style":81},[78,79],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31142738\u002Fwide_form_2.png",[64,95,96],{},[67,97,98,101],{},[70,99,100],{},"Mixed-form data"," is a hybrid of long-form and wide-form data.",[75,103],{"className":104,"alt":40,"src":105,"style":106},[78,79],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31142805\u002Fmixed_form.png","width: 70%;",[23,108,110],{"id":109},"dash-layout","Dash Layout",[15,112,113,114,118,119,122],{},"Dash apps are composed of two parts. The first part is the \"",[115,116,117],"em",{},"layout","\" of the app and it describes what the application looks like. The second part describes the interactivity of the application, it's \"",[115,120,121],{},"callbacks\"",".",[15,124,125,126,129,130,133],{},"\"",[115,127,128],{},"Layout\""," is composed of a tree of \"",[115,131,132],{},"components","\".",[15,135,136],{},"Dash provides many types of components: Dash HTML Components, Dash Core Components, Dash DataTable, Dash DAQ, Dash Bootstrap Components,...",[15,138,139],{},"In this article we use: Dash HTML Components and Dash Core Components.",[141,142,144],"h3",{"id":143},"dash-html-components","Dash HTML Components",[15,146,147],{},"A function that provides HTML-style components, used to define HTML tags for layouts.",[15,149,150,151],{},"To use Dash HTML Components we need to import to our .py file as follows: ",[38,152,153],{},"from dash import html",[15,155,156],{},"Example:",[15,158,159],{},[115,160,161],{},"html_demo.py",[31,163,166],{"className":164,"code":165,"language":36},[34],"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",[38,167,165],{"__ignoreMap":40},[15,169,170,173,174,177],{},[38,171,172],{},"html.H1(children='Hello Dash')"," component generates a ",[38,175,176],{},"\u003Ch1>Hello Dash\u003C\u002Fh1>"," on the browser.",[15,179,180,181,184],{},"Just like HTML tags, we can completely change the style of html_component with the \"",[115,182,183],{},"style","\" property.",[15,186,187,188],{},"Example: ",[38,189,190],{},"html.H1('Hello Dash', style={'textAlign': 'center', 'color': '#7FDBFF'})",[15,192,193,194,122],{},"The above code is rendered as ",[38,195,196],{},"\u003Ch1 style=\"text-align: center; color: #7FDBFF\">Hello Dash\u003C\u002Fh1>",[15,198,199],{},"There are a few important differences between the Dash HTML Components and the HTML attributes:",[64,201,202,205,215,226],{},[67,203,204],{},"The style property in HTML is a semicolon-separated string. In Dash, you can just supply a dictionary.",[67,206,207,208,211,212,133],{},"The keys in the style dictionary are camelCased. So, instead of \"",[115,209,210],{},"text-align","\", it's \"",[115,213,214],{},"textAlign",[67,216,217,218,221,222,225],{},"The HTML \"",[115,219,220],{},"class","\" attribute is \"",[115,223,224],{},"className","\" in Dash.",[67,227,228,229,232],{},"The children of the HTML tag is specified through the \"",[115,230,231],{},"children","\" keyword argument.",[15,234,235,236],{},"In addition, instead of using the style directly, we can use the CSS file to define the style for the layout, for details, refer to: ",[237,238,239],"a",{"href":239,"rel":240},"https:\u002F\u002Fdash.plotly.com\u002Fexternal-resources",[241],"nofollow",[15,243,244,245],{},"You can view all of the available components in the Dash HTML Components Gallery: ",[237,246,247],{"href":247,"rel":248},"https:\u002F\u002Fdash.plotly.com\u002Fdash-html-components",[241],[141,250,252],{"id":251},"dash-core-components","Dash Core Components",[15,254,255,256],{},"Includes a set of higher-level components like dropdowns, checkboxes, radio items, graphs, and more. You can view all of the available components in the Dash Core Components Gallery: ",[237,257,258],{"href":258,"rel":259},"https:\u002F\u002Fdash.plotly.com\u002Fdash-core-components",[241],[15,261,262,263],{},"To use Dash Core Components we need to import to our .py file as follows: ",[38,264,265],{},"from dash import dcc",[15,267,268,269,272,273,275],{},"Among core components, \"",[115,270,271],{},"Graph","\" is an important component for Data Visualization. “",[115,274,271],{},"” renders interactive data visualizations using the open source plotly.js graphing library. Plotly.js supports over 35 chart types and renders charts in both vector-quality SVG and high-performance WebGL. A small note here is that Plotly.js is only used to render to the browser (this is done by Dash), but when coding we will use the Plotly.py library (provided when installing Dash) rather than coding with javascript.",[15,277,278,279,281],{},"To see how to use the \"",[115,280,271],{},"\" component let's go to an example that displays the csv data to the browser as a line graph.",[15,283,284],{},[115,285,286],{},"csv\u002Fgraph_sample.csv",[31,288,291],{"className":289,"code":290,"language":36},[34],"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",[38,292,290],{"__ignoreMap":40},[15,294,295],{},"First we need to use pandas to load the csv file",[31,297,300],{"className":298,"code":299,"language":36},[34],"df = pd.read_csv('csv\u002Fgraph_sample.csv')\n",[38,301,299],{"__ignoreMap":40},[15,303,304],{},"Print the variable df to the console to see its structure",[31,306,309],{"className":307,"code":308,"language":36},[34],"print(df)\n",[38,310,308],{"__ignoreMap":40},[75,312],{"className":313,"alt":40,"src":314,"style":106},[78,79],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31144341\u002Fexample_wide_form.png",[15,316,317],{},"Does this look familiar to you? Exactly, it is the wide-form DataFrame that we mentioned in the About Pandas above!",[15,319,320],{},"The next step is to convert the DateTime column's data from string to datetime so that our chart shows the exact date and time of the data.",[31,322,325],{"className":323,"code":324,"language":36},[34],"df['DateTime'] = pd.to_datetime(df['DateTime'], format='%Y%m%d %H:%M:%S.%f')\n",[38,326,324],{"__ignoreMap":40},[15,328,329],{},"Now we create a line figure using plotly express",[31,331,334],{"className":332,"code":333,"language":36},[34],"line_fig = px.line(df, x='DateTime', y=['DATA 1', 'DATA 2', 'DATA 3', 'DATA 4'])\n",[38,335,333],{"__ignoreMap":40},[15,337,338],{},"Pass the figure to the Graph component",[31,340,343],{"className":341,"code":342,"language":36},[34],"app.layout = html.Div(children=[\n    dcc.Graph(id='graph', figure=line_fig)\n])\n",[38,344,342],{"__ignoreMap":40},[15,346,347],{},"Completed code:",[15,349,350],{},[115,351,352],{},"graph_demo.py",[31,354,357],{"className":355,"code":356,"language":36},[34],"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",[38,358,356],{"__ignoreMap":40},[15,360,361],{},"In the terminal run the command:",[31,363,366],{"className":364,"code":365,"language":36},[34],"python graph_demo.py\n",[38,367,365],{"__ignoreMap":40},[15,369,370,371,375],{},"Then visit ",[237,372,373],{"href":373,"rel":374},"http:\u002F\u002F127.0.0.1:8050\u002F",[241]," to see the result",[75,377],{"className":378,"alt":40,"src":379,"style":380},[78,79],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31144923\u002Fexample_graph-1024x373.png","width: 100%;",[15,382,383],{},"In the example above:",[64,385,386,389],{},[67,387,388],{},"Pandas library is used to process input data (read csv, convert data of DateTime column from string to datetime).",[67,390,391],{},"Plotly Express (in the Plotly.py library) is responsible for specifying the graph type (line, scatter,...), x-axis, y-axis,... of the Graph output.",[23,393,395],{"id":394},"dash-callbacks","Dash Callbacks",[15,397,398],{},"Callback functions: functions that are automatically called by Dash whenever an input component's property changes, in order to update some property in another component (the output).",[15,400,401],{},"To understand Callbacks let's come up with an example of filtering data by date, with input from the dcc.DatePickerRange component:",[15,403,404],{},[115,405,406],{},"csv\u002Fcallbacks_sample.csv",[31,408,411],{"className":409,"code":410,"language":36},[34],"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",[38,412,410],{"__ignoreMap":40},[15,414,415],{},[115,416,417],{},"callbacks_demo.py",[31,419,422],{"className":420,"code":421,"language":36},[34],"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",[38,423,421],{"__ignoreMap":40},[15,425,426,427,430,431,434,435,438,439,442,443,133],{},"In Dash, the inputs and outputs of our application are simply the properties of a particular component. In this example, our input are the \"",[115,428,429],{},"start_date","\" and \"",[115,432,433],{},"end_date","\" properties of the component that has the ID \"",[115,436,437],{},"date-picker-range","\". Our output is the \"",[115,440,441],{},"figure","\" property of the component with the ID \"",[115,444,445],{},"scatter-graph",[15,447,448,449,452,453,456,457,459,460,462,463,465,466,469],{},"Whenever an input property changes, the function that the ",[115,450,451],{},"@callback"," decorator wraps will get called automatically. Dash provides this callback function with the new value of the input property as its argument (in the above example function ",[115,454,455],{},"update_figure"," has 2 arguments: ",[115,458,429],{},", ",[115,461,433],{},"), and Dash updates the property of the output component with whatever was returned by the function (in the example above function ",[115,464,455],{}," returns ",[115,467,468],{},"scatter_fig",").",[15,471,472,473,476,477,375],{},"In the terminal run the command ",[38,474,475],{},"python callbacks_demo.py"," and go to ",[237,478,373],{"href":373,"rel":479},[241],[75,481],{"className":482,"alt":40,"src":483,"style":380},[78,79],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31145606\u002Fcallback_demo_pic1-1024x381.png",[15,485,486,487],{},"After changing ",[115,488,433],{},[75,490],{"className":491,"alt":40,"src":492,"style":380},[78,79],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31145648\u002Fcallbacks_demo_pic2-1024x387.png",[23,494,496],{"id":495},"optimizing-and-adding-functionality","Optimizing and adding functionality",[15,498,499],{},"In this part, we take the code in the Callbacks section to optimize and add functionality to it.",[141,501,503],{"id":502},"read-n-data","Read n DATA",[15,505,506],{},"Currently we are hard-setting the number of input data is 4.",[31,508,511],{"className":509,"code":510,"language":36},[34],"scatter_fig = px.scatter(filtered_df, x='DateTime', y=['DATA 1', 'DATA 2', 'DATA 3', 'DATA 4'])\n",[38,512,510],{"__ignoreMap":40},[15,514,515],{},"Assuming we have any amount of data DATA 1, DATA 2, ..., DATA n, with the above code we can only read and display 4 data.",[15,517,518],{},"To read and display the graph n DATA, we need to modify the code a little bit:",[31,520,523],{"className":521,"code":522,"language":36},[34],"# 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",[38,524,522],{"__ignoreMap":40},[141,526,528],{"id":527},"read-config-from-csv-header","Read config from CSV header",[15,530,531],{},"Consider the header of the CSV as follows",[31,533,536],{"className":534,"code":535,"language":36},[34],"DateTime(yyyyMMdd HH:mm:ss.fff),DATA 1(minFilter=20;maxFilter=100),DATA 2(maxFilter=140),DATA 3,DATA 4,DATA 5\n",[38,537,535],{"__ignoreMap":40},[15,539,540],{},"We will add the function to read the config from the header above:",[64,542,543,546],{},[67,544,545],{},"Read the config of the DateTime column to set the date time format (currently set hard in the code).",[67,547,548,549,459,552,555,556,558,559,561],{},"Read config ",[115,550,551],{},"minFilter",[115,553,554],{},"maxFilter"," of DATA columns to filter out data with values less than ",[115,557,551],{}," and greater than ",[115,560,554],{}," of that DATA column.",[15,563,564,565,568],{},"First add the file ",[115,566,567],{},"utils.py"," containing common functions",[31,570,573],{"className":571,"code":572,"language":36},[34],"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",[38,574,572],{"__ignoreMap":40},[15,576,577],{},"In the above code:",[64,579,580,587],{},[67,581,582,583,586],{},"The ",[115,584,585],{},"convert_py_datetime_format"," function is used to convert the format of yyyyMMdd HH:mm:ss.fff to the Python format.",[67,588,582,589,592,593,596,597,600,601],{},[115,590,591],{},"extract_csv_col_config"," function will take the name of the column containing the config and return the column name that has removed the config string along with an array containing the configs of that column. For example ",[38,594,595],{},"DATA 1(minFilter=20;maxFilter=100)"," will return ",[38,598,599],{},"DATA 1"," and array ",[38,602,603],{},"[(minFilter, 20), (maxFilter, 100)]",[15,605,606,607,610,611],{},"Next add function ",[115,608,609],{},"process_csv_variable"," to ",[115,612,613],{},"app.py",[31,615,618],{"className":616,"code":617,"language":36},[34],"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",[38,619,617],{"__ignoreMap":40},[15,621,622,623,625],{},"The function ",[115,624,609],{}," will receive a DataFrame, read the config from the column names, process the data according to the config, and return a DataFrame after processing.",[15,627,628,629,632],{},"Now we add ",[115,630,631],{},"csv\u002Fapp_sample.csv"," file to test",[31,634,637],{"className":635,"code":636,"language":36},[34],"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",[38,638,636],{"__ignoreMap":40},[15,640,472,641,644,645,375],{},[38,642,643],{},"python app.py"," and visit ",[237,646,373],{"href":373,"rel":647},[241],[75,649],{"className":650,"alt":40,"src":651,"style":380},[78,79],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31150435\u002Fapp_demo1-1024x371.png",[15,653,654],{},"To make it easier to check the results, we hide the other data and only show DATA 1",[75,656],{"className":657,"alt":40,"src":658,"style":380},[78,79],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F12\u002F31150508\u002Fapp_demo2-1024x373.png",[15,660,661],{},"We see that data with values less than 20 and greater than 100 has been filtered out.",[10,663,665],{"id":664},"source-code","Source code",[15,667,668],{},[237,669,670],{"href":670,"rel":671},"https:\u002F\u002Fgitlab.com\u002Fbwv-hp\u002Fpython-dash-sample",[241],[10,673,675],{"id":674},"references","References",[15,677,678],{},[237,679,680],{"href":680,"rel":681},"https:\u002F\u002Fdash.plotly.com\u002F",[241],[15,683,684],{},[237,685,686],{"href":686,"rel":687},"https:\u002F\u002Fpandas.pydata.org\u002Fdocs\u002F",[241],{"title":40,"searchDepth":689,"depth":689,"links":690},2,[691,692,693,698,699],{"id":25,"depth":689,"text":26},{"id":52,"depth":689,"text":53},{"id":109,"depth":689,"text":110,"children":694},[695,697],{"id":143,"depth":696,"text":144},3,{"id":251,"depth":696,"text":252},{"id":394,"depth":689,"text":395},{"id":495,"depth":689,"text":496,"children":700},[701,702],{"id":502,"depth":696,"text":503},{"id":527,"depth":696,"text":528},"tech talk","NGHIA NGUYEN TRUNG","2022-01-25","Introduction to Dash Dash is an open source library released under the permissive MIT license. Written on top of Plotly.js and React.js, Dash is ideal for building and deploying data apps with customized user interfaces. Dash is simple enough that you can bind a user interface to your code in less than 10 minutes. Dash apps are rendered in the web browser, so it can run on cross-platform and also mobile devices.","md",{},true,"\u002Fnews\u002Ftruc-quan-hoa-du-lieu-bang-python-dash",null,{"title":5,"description":706},"news\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","26PYMCXTw7kHwD7cNeqmsWPoqy9APUDr8_WOdt0-bfs",1784703331447]