<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Iyed Ghedamsi</title>
<link>https://iyedg.com/</link>
<atom:link href="https://iyedg.com/index.xml" rel="self" type="application/rss+xml"/>
<description>Building Data Solutions for Social Good</description>
<generator>quarto-1.9.37</generator>
<lastBuildDate>Tue, 20 Jul 2021 21:00:00 GMT</lastBuildDate>
<item>
  <title>The vaccination campaign in Tunisia: a blameless crime ?</title>
  <dc:creator>Iyed Ghedamsi</dc:creator>
  <link>https://iyedg.com/posts/vaccination_campaign_tunisia/</link>
  <description><![CDATA[ 





<blockquote class="blockquote">
<p><strong>Disclaimer I</strong>: The data used throughout this piece has been scraped from the <em>‘open data’</em> section of <a href="https://evax.tn">EVAX</a>. It is very possible that I made a mistake collecting / interpreting the data given that It was collected in non-traditional ways. The code I used is available in the end of the article, <a href="https://github.com/iyedg/iyedg.github.io/blob/develop/content/blog/vaccination_campaign_tunisia/notebook/scraping.ipynb">please check it for yourself</a> .</p>
</blockquote>
<blockquote class="blockquote">
<p><strong>Disclaimer II</strong>: This is an opinion article despite it having graphs and numbers. It should not be taken as nothing more than a random stranger’s opinion on the internet.</p>
</blockquote>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>Assigning responsibilities in the case of the mismanagements of a public health crisis is nothing but a basic expectation from democratically elected officials. But what if citizens are the culprits ? So we are told. In this short exploration, I go through one aspect of the efforts against the COVID-19 pandemic in Tunisia: the registration for vaccinations.</p>
</section>
<section id="citizen-awareness-the-tale-of-a-scapegoat" class="level2">
<h2 class="anchored" data-anchor-id="citizen-awareness-the-tale-of-a-scapegoat">Citizen awareness: the tale of a scapegoat</h2>
<p><img src="https://iyedg.com/posts/vaccination_campaign_tunisia/images/cum_line_plot.webp" class="img-fluid"></p>
<p>Looking at the two plots above outlining the number of registrations on the official platform <strong>EVAX</strong>, an upwards trend in the population and across all age groups is clear. Although some groups have higher registration rates such as ages <em>50-60</em> and <em>60-70</em>, the other groups do show an accelerated registration rate starting from June, most notably the <em>18-30</em> group. Based solely on these observations one might be tempted to question the dominant narrative that <em>Tunisians do not want to get vaccinated</em>. Yet a rephrasing of the of this blame pushes us to further analysis: <em>Are Tunisians registering fast enough ?</em></p>
<section id="enter-the-dip" class="level3">
<h3 class="anchored" data-anchor-id="enter-the-dip">Enter: The dip</h3>
<p><img src="https://iyedg.com/posts/vaccination_campaign_tunisia/images/stream_plot.webp" class="img-fluid"></p>
<p>A first observation to make from the graph above is the peculiar dip in the number of registrations for the vaccinations by the end of January. Yet looking at how the trend is reversed right after the beginning of the vaccination campaign, it seems to me that an explanation, and an answer, arise. With 52 days between the launch of EVAX and the first day of the vaccination campaign, registration efforts were bound to fizzle out with no immediate or foreseeable outcome in sight. More importantly, a variety of phenomena can explain the registration rate of Tunisians following the beginning of the vaccination campaign. Firstly, the economic crisis and the inconsistent signals provided by the government regarding their ability to purchase the necessary vaccine quantities are certainly a hindrance for any effort to onboard people on EVAX. Secondly, a notable failure of the COVID-19 national strategy was the lack of communication on the safety of the vaccines. The void left by this absence left room for a variety of rumors and misinformation / disinformation to plague the public discourse about vaccines.</p>
</section>
<section id="the-crestfallen-bunch" class="level3">
<h3 class="anchored" data-anchor-id="the-crestfallen-bunch">The crestfallen bunch</h3>
<p>Right before Eid al-Adha, a Facebook post on the Health ministry’s page announced <a href="https://www.facebook.com/santetunisie.rns.tn/posts/4322448191127585"><em>Vaccination Open Days</em></a> on the 19<sup>th</sup> of July, at 3:21 PM, for anyone older than 18. The announcement caused a lot of confusion and excitement. A registration frenzy ensued: 45 566 people between the ages 18 and 30 registered on the 19<sup>th</sup>. That’s 17 211 more registrations than the next day with the most registrations for that age group. The interest of the young groups, however, precedes this event. The graph below shows that the <em>30-40</em> had climbed two positions to become the second most registering age group by the 12<sup>th</sup> of July. As well as the <em>18-30</em> group that became the highest ranking group on the 16<sup>th</sup> of July. Thus dispelling the last drop of doubt that Tunisians are <em>‘unaware’</em> of the importance of vaccinations. Instead, what Tunisians needed was .. vaccines.</p>
<blockquote class="blockquote">
<p><strong><em>Crestfallen</em></strong> : disappointed and sad because of having failed unexpectedly. – <cite>Cambridge Dictionary</cite></p>
</blockquote>
<p><img src="https://iyedg.com/posts/vaccination_campaign_tunisia/images/bump_plot.webp" class="img-fluid"></p>
<p>The disappointment followed the Eid al-Adha’s episode is one to be remembered, hopefully long enough to punish those responsible. A simple look at the data readily available on EVAX would have made is sufficiently clear that calling upon <em>every Tunisian old enough to be vaccinated</em> within two days was an exercise in stupidity and tomfoolery. With the absence of common sense that is.</p>
</section>
</section>
<section id="the-road-ahead" class="level2">
<h2 class="anchored" data-anchor-id="the-road-ahead">The road ahead:</h2>
<p><img src="https://iyedg.com/posts/vaccination_campaign_tunisia/images/comp_plot.webp" class="img-fluid"></p>
<p>It goes without saying that engaging in an honest an thorough analysis of the bottlenecks slowing down the vaccination process is a must. Between the over-worked and understaffed health workers and the saturation of the whole health system of the country, clear measures must be taken to firstly curb the spread of the virus and to efficiently vaccinate the remainder of the population.</p>
<p>Relying on the <em>‘citizen’s awareness’</em> has become a meme that simultaneously denigrates any civilised behaviour from Tunisians and branding them as <em>de facto</em> savages until they prove otherwise, and a representation of a weak political class that can do nothing but serve the rich and blame the poor. I say, citizens are aware, as aware as their material conditions allow them to be.</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>COVID-19</category>
  <category>Tunisia</category>
  <guid>https://iyedg.com/posts/vaccination_campaign_tunisia/</guid>
  <pubDate>Tue, 20 Jul 2021 21:00:00 GMT</pubDate>
</item>
<item>
  <title>Opening up the Tunisian Institute of Statistics’ poverty report of 2020</title>
  <dc:creator>Iyed Ghedamsi</dc:creator>
  <link>https://iyedg.com/posts/poverty_rate_tunisia_2020/</link>
  <description><![CDATA[ 





<p>As is the case with most publication from Tunisian public institutions that generate data, the <strong>National Institute of Statistics</strong> (NIS) has recently released a <a href="www.ins.tn%2Fsites%2Fdefault%2Ffiles%2Fpublication%2Fpdf%2FCarte de la pauvreté en Tunisie_final.pdf">report on poverty</a> in Tunisia as a … PDF file. The Tunisian citizen in me cringed, the data nerd decided it would make a good project to showcase how to transform a PDF into a more open format, and even throw in some interactive data visualization.</p>
<p>Before moving further in this blog post, it is important to establish what it does, and what it does not.</p>
<p><strong>What this is not</strong> * An analysis of the poverty data in Tunisia, although I am very tempted to do it. * A bashing of the <strong>NIS</strong>, they are probably overworked, paid too little, and lack the necessary training to operate and maintain an open data pipeline.</p>
<p><strong>What this is</strong> * A make-up routine for a PDF file using Python, Tabula, Plotly and Streamlit.</p>
<p>If you want to play with the data file you can find it in this <a href="https://raw.githubusercontent.com/iyedg/poverty_rate_dashboard/develop/data/processed/poverty_rate_Tunisia_2020.csv">link</a>. The interactive dashboard is viewable in this <a href="https://share.streamlit.io/iyedg/poverty_rate_dashboard/develop/poverty_rate_dashboard/main.py">link</a></p>
<section id="data-extraction-from-pdf." class="level2">
<h2 class="anchored" data-anchor-id="data-extraction-from-pdf.">Data extraction from PDF.</h2>
<p>The first step of this project is evidently transforming the data inside the PDF into structured data. For this purpose, we will use two excellent Python libraries: Tabula for PDF tables’ manipulation, and Pandas for data cleaning and reshaping.</p>
<div id="011bd0b6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tabula</span>
<span id="cb1-2">raw_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tabula.read_pdf(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NIS_poverty_report.pdf"</span>,</span>
<span id="cb1-3">                          pages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>,</span>
<span id="cb1-4">                          multiple_tables<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb1-5">                          pandas_options<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"header"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>})[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div></div>
</div>
<p>In this snippet, we are telling Tabula to read the file <code>NIS_poverty_report.pdf</code>, on page <code>40</code> specifically, which has <code>multiple_tables</code>. Note that the parameter <code>multiple_tables</code> implies that Tabula will return a list of pandas Data Frames, which is why we use the first value in the return value of the <code>read_pdf</code> function call. This will become relevant when extracting the data for <strong>Mednine</strong> and <strong>Tataouine</strong> which happen to be on the same page.</p>
<p>A nice tutorial about table extraction from PDF using Table can be found in this <a href="https://aegis4048.github.io/parse-pdf-files-while-retaining-structure-with-tabula-py">link</a></p>
<div id="f5f2ff82" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Will extract the first table identified on page 82</span></span>
<span id="cb2-2"></span>
<span id="cb2-3">mednine_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tabula.read_pdf(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NIS_poverty_report.pdf"</span>,</span>
<span id="cb2-4">                          pages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">82</span>,</span>
<span id="cb2-5">                          multiple_tables<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb2-6">                          pandas_options<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"header"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>})[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb2-7"></span>
<span id="cb2-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Will extract the second table identified on page 82</span></span>
<span id="cb2-9"></span>
<span id="cb2-10">tataouine_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tabula.read_pdf(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NIS_poverty_report.pdf"</span>,</span>
<span id="cb2-11">                          pages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">82</span>,</span>
<span id="cb2-12">                          multiple_tables<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb2-13">                          pandas_options<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"header"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>})[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span></code></pre></div></div>
</div>
<p>The other important argument to pay attention to with tabula is <code>pandas_options</code>. To properly understand what it does, we simply need to think of the dictionary passed to it as the python convention for passing key word arguments in <code>**kwargs</code>. Essentially, after reading the table from PDF, tabula will read the result as a CSV using pandas according to the key word arguments passed in <code>pandas_options</code>.</p>
<p>What remains now is to go through the pages specific to each governorate, extract their corresponding table, then merge them into the final dataset. The following snippet provides an overview of the process in code. the full code is available <a href="https://github.com/iyedg/poverty_rate_dashboard/blob/develop/poverty_rate_dashboard/process_raw_pdf.py">here</a>)</p>
<div id="64e17e9a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> process_raw_pdf():</span>
<span id="cb3-2">    governorates_pages <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb3-3">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tunis"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>,</span>
<span id="cb3-4">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ariana"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>,</span>
<span id="cb3-5">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ben Arous"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">44</span>,</span>
<span id="cb3-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Manouba"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>,</span>
<span id="cb3-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Nabeul"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">49</span>,</span>
<span id="cb3-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Zagouan"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>,</span>
<span id="cb3-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bizerte"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">52</span>,</span>
<span id="cb3-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Beja"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">55</span>,</span>
<span id="cb3-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Jandouba"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">56</span>,</span>
<span id="cb3-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Kef"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">58</span>,</span>
<span id="cb3-13">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Seliana"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">62</span>,</span>
<span id="cb3-14">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sousse"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>,</span>
<span id="cb3-15">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Monastir"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">68</span>,</span>
<span id="cb3-16">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mahdia"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>,</span>
<span id="cb3-17">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sfax"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">71</span>,</span>
<span id="cb3-18">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Kairouan"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">73</span>,</span>
<span id="cb3-19">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Kasserine"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">75</span>,</span>
<span id="cb3-20">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sidi Bouzid"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">76</span>,</span>
<span id="cb3-21">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gabes"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">79</span>,</span>
<span id="cb3-22">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Médnine"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">82</span>,</span>
<span id="cb3-23">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tataouine"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">82</span>,</span>
<span id="cb3-24">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gafsa"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">85</span>,</span>
<span id="cb3-25">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tozeur"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>,</span>
<span id="cb3-26">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Kebili"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">87</span>,</span>
<span id="cb3-27">    }</span>
<span id="cb3-28"></span>
<span id="cb3-29">    governorates_dfs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb3-30"></span>
<span id="cb3-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> governorate_name, page <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> governorates_pages.items():</span>
<span id="cb3-32">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> governorate_name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tataouine"</span>:</span>
<span id="cb3-33">            table_index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb3-34">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb3-35">            table_index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb3-36">        df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb3-37">            tabula.read_pdf(</span>
<span id="cb3-38">                input_pdf_path,</span>
<span id="cb3-39">                pages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>page,</span>
<span id="cb3-40">                multiple_tables<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb3-41">                pandas_options<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"header"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>},</span>
<span id="cb3-42">            )[table_index]</span>
<span id="cb3-43">            .pipe(cleaning_pipeline) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Using a pandas pipelines to cleanup individual data frames</span></span>
<span id="cb3-44">            .assign(Gouvernorat<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>governorate_name)</span>
<span id="cb3-45">        )</span>
<span id="cb3-46"></span>
<span id="cb3-47">        governorates_dfs.append(df)</span>
<span id="cb3-48">    combined_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat(governorates_dfs, ignore_index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb3-49">    combined_df.to_csv(</span>
<span id="cb3-50">        here(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data/processed/poverty_rate_Tunisia_2020.csv"</span>), index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="cb3-51">    )</span>
<span id="cb3-52">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> combined_df</span></code></pre></div></div>
</div>
</section>
<section id="agumenting-the-data-fuzzy-string-matching" class="level2">
<h2 class="anchored" data-anchor-id="agumenting-the-data-fuzzy-string-matching">Agumenting the data: fuzzy string matching</h2>
<p>The dataset we have extracted thus far can be visualized as is to get insights about regional differences in poverty rates, and how that can be related to primary and secondary schools abandonment rates. That is all good and well, but I wanted a map (the technical term is a Choropleth map, from the Greek <em>Choros</em> for area and <em>Plethos</em> for multitude).</p>
<p>As such, I have embarked on the journey to augment the dataset with the administrative borders of Tunisian delegations. Getting the data was relatively simple, the kind people at <a href="https://www.data4tunisia.org">data4tunisia</a> host a platform where a variety of entities and people can share their data publically, which is <a href="https://www.data4tunisia.org/en/datasets/decoupage-de-la-tunisie-geojson-et-shapefile/#_">where</a> I got the geo data for Tunisian delegations.</p>
<p>The challenge that jumps at us right away is that the key variables used to join the datasets i.e.&nbsp;the governorate name and the delegation name are not written the same way. To better illustrate the problem, let us look at a subset of the municipality names we are trying to match.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: left;">Delegation name form NIS</th>
<th style="text-align: left;">Delegation name from Geo data</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Ettahrir</td>
<td style="text-align: left;">El Tahrir</td>
</tr>
<tr class="even">
<td style="text-align: left;">Tina</td>
<td style="text-align: left;">Thyna</td>
</tr>
<tr class="odd">
<td style="text-align: left;">La Medina</td>
<td style="text-align: left;">Médina</td>
</tr>
<tr class="even">
<td style="text-align: left;">Ariana Ville</td>
<td style="text-align: left;">Ariana Médina</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Souk Lahad</td>
<td style="text-align: left;">Souk El Ahed</td>
</tr>
<tr class="even">
<td style="text-align: left;">Elksar</td>
<td style="text-align: left;">Ksar</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Boumhel Bassatine</td>
<td style="text-align: left;">Boumhel</td>
</tr>
<tr class="even">
<td style="text-align: left;">Sidi Ali Ben Nasrallah</td>
<td style="text-align: left;">Nasrallah</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Sfax Ville</td>
<td style="text-align: left;">Sfax Médina</td>
</tr>
<tr class="even">
<td style="text-align: left;">Sidi Amor Bou Hajla</td>
<td style="text-align: left;">Bouhajla</td>
</tr>
</tbody>
</table>
<p>With 264 unique delegation names <em>(there are 264 delegations but two of them are called <strong>Ezzouhour</strong>)</em>, this task has to be done programatically. The best way I found to deal with this is by formulating the challenge as an <a href="https://en.wikipedia.org/wiki/Assignment_problem"><strong>Assignment problem</strong></a>. In essence, this entails building a cost matrix between the names from the NIS and the names from the Geo data where the cost is some measure of distance between the text of the two names, then running an optimization algorithm that will assign matching names such as to minimize the total distance <em>(or cost)</em> between the matched names.</p>
<p>For the implementation of this step we resort to two excellent python packages: <a href="https://github.com/life4/textdistance">TextDistance</a> and <a href="https://github.com/scipy/scipy">SciPy</a>. With TextDistance we have access to a wide variety of text distance metrics, but I have settled through experimentation on the <a href="https://en.wikipedia.org/wiki/Jaccard_index">Jaccard Index</a>. As for the optimization algorithm we will use the <a href="https://en.wikipedia.org/wiki/Hungarian_algorithm">Hungarian algorithm</a>.</p>
<div id="7d6d8ffd" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">NSI_names <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb4-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ettahrir"</span>,</span>
<span id="cb4-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tina"</span>,</span>
<span id="cb4-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"La Medina"</span>,</span>
<span id="cb4-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ariana Ville"</span>,</span>
<span id="cb4-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Souk Lahad"</span>,</span>
<span id="cb4-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Elksar"</span>,</span>
<span id="cb4-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Boumhel Bassatine"</span>,</span>
<span id="cb4-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sidi Ali Ben Nasrallah"</span>,</span>
<span id="cb4-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sfax Ville"</span>,</span>
<span id="cb4-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sidi Amor Bou Hajla"</span>,</span>
<span id="cb4-12">]</span>
<span id="cb4-13">geodata_names <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb4-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"El Tahrir"</span>,</span>
<span id="cb4-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Thyna"</span>,</span>
<span id="cb4-16">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Médina"</span>,</span>
<span id="cb4-17">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ariana Médina"</span>,</span>
<span id="cb4-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Souk El Ahed"</span>,</span>
<span id="cb4-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ksar"</span>,</span>
<span id="cb4-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Boumhel"</span>,</span>
<span id="cb4-21">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Nasrallah"</span>,</span>
<span id="cb4-22">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sfax Médina"</span>,</span>
<span id="cb4-23">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bouhajla"</span>,</span>
<span id="cb4-24">]</span>
<span id="cb4-25"></span>
<span id="cb4-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># We shuffle them randomly to avoid having the existing order affecting the algorithm</span></span>
<span id="cb4-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># even though theoretically it does not matter</span></span>
<span id="cb4-28">shuffle(NSI_names)</span>
<span id="cb4-29">shuffle(geodata_names)</span></code></pre></div></div>
</div>
<p>Now we compute the cost matrix as follows:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"></span>
<span id="cb5-2">pairs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> product(NSI_names, geodata_names)</span>
<span id="cb5-3"></span>
<span id="cb5-4">scores <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array(</span>
<span id="cb5-5">    [textdistance.jaccard.normalized_distance(q, c) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> q, c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> pairs]</span>
<span id="cb5-6">).reshape((<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(NSI_names), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(geodata_names)))</span></code></pre></div></div>
<table class="caption-top table">
<colgroup>
<col style="width: 15%">
<col style="width: 7%">
<col style="width: 7%">
<col style="width: 10%">
<col style="width: 6%">
<col style="width: 6%">
<col style="width: 8%">
<col style="width: 9%">
<col style="width: 6%">
<col style="width: 8%">
<col style="width: 11%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;"></th>
<th style="text-align: right;">Boumhel</th>
<th style="text-align: right;">Bouhajla</th>
<th style="text-align: right;">Souk El Ahed</th>
<th style="text-align: right;">Thyna</th>
<th style="text-align: right;">Médina</th>
<th style="text-align: right;">Nasrallah</th>
<th style="text-align: right;">Sfax Médina</th>
<th style="text-align: right;">Ksar</th>
<th style="text-align: right;">El Tahrir</th>
<th style="text-align: right;">Ariana Médina</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Souk Lahad</td>
<td style="text-align: right;">0.785714</td>
<td style="text-align: right;">0.615385</td>
<td style="text-align: right;">0.533333</td>
<td style="text-align: right;">0.846154</td>
<td style="text-align: right;">0.857143</td>
<td style="text-align: right;">0.8125</td>
<td style="text-align: right;">0.6875</td>
<td style="text-align: right;">0.923077</td>
<td style="text-align: right;">0.8125</td>
<td style="text-align: right;">0.789474</td>
</tr>
<tr class="even">
<td style="text-align: left;">Ariana Ville</td>
<td style="text-align: right;">0.882353</td>
<td style="text-align: right;">0.823529</td>
<td style="text-align: right;">0.8</td>
<td style="text-align: right;">0.866667</td>
<td style="text-align: right;">0.8</td>
<td style="text-align: right;">0.6875</td>
<td style="text-align: right;">0.722222</td>
<td style="text-align: right;">0.857143</td>
<td style="text-align: right;">0.6875</td>
<td style="text-align: right;">0.529412</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Tina</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">0.909091</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">0.5</td>
<td style="text-align: right;">0.571429</td>
<td style="text-align: right;">0.916667</td>
<td style="text-align: right;">0.75</td>
<td style="text-align: right;">0.857143</td>
<td style="text-align: right;">0.7</td>
<td style="text-align: right;">0.785714</td>
</tr>
<tr class="even">
<td style="text-align: left;">Sidi Ali Ben Nasrallah</td>
<td style="text-align: right;">0.84</td>
<td style="text-align: right;">0.8</td>
<td style="text-align: right;">0.692308</td>
<td style="text-align: right;">0.875</td>
<td style="text-align: right;">0.833333</td>
<td style="text-align: right;">0.590909</td>
<td style="text-align: right;">0.730769</td>
<td style="text-align: right;">0.869565</td>
<td style="text-align: right;">0.76</td>
<td style="text-align: right;">0.6</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Elksar</td>
<td style="text-align: right;">0.916667</td>
<td style="text-align: right;">0.833333</td>
<td style="text-align: right;">0.8</td>
<td style="text-align: right;">0.9</td>
<td style="text-align: right;">0.909091</td>
<td style="text-align: right;">0.636364</td>
<td style="text-align: right;">0.9375</td>
<td style="text-align: right;">0.571429</td>
<td style="text-align: right;">0.636364</td>
<td style="text-align: right;">0.882353</td>
</tr>
<tr class="even">
<td style="text-align: left;">Boumhel Bassatine</td>
<td style="text-align: right;">0.588235</td>
<td style="text-align: right;">0.611111</td>
<td style="text-align: right;">0.73913</td>
<td style="text-align: right;">0.842105</td>
<td style="text-align: right;">0.85</td>
<td style="text-align: right;">0.761905</td>
<td style="text-align: right;">0.782609</td>
<td style="text-align: right;">0.894737</td>
<td style="text-align: right;">0.761905</td>
<td style="text-align: right;">0.8</td>
</tr>
<tr class="odd">
<td style="text-align: left;">La Medina</td>
<td style="text-align: right;">0.933333</td>
<td style="text-align: right;">0.866667</td>
<td style="text-align: right;">0.833333</td>
<td style="text-align: right;">0.833333</td>
<td style="text-align: right;">0.5</td>
<td style="text-align: right;">0.875</td>
<td style="text-align: right;">0.461538</td>
<td style="text-align: right;">0.916667</td>
<td style="text-align: right;">0.8</td>
<td style="text-align: right;">0.533333</td>
</tr>
<tr class="even">
<td style="text-align: left;">Sidi Amor Bou Hajla</td>
<td style="text-align: right;">0.761905</td>
<td style="text-align: right;">0.65</td>
<td style="text-align: right;">0.652174</td>
<td style="text-align: right;">0.956522</td>
<td style="text-align: right;">0.863636</td>
<td style="text-align: right;">0.833333</td>
<td style="text-align: right;">0.75</td>
<td style="text-align: right;">0.904762</td>
<td style="text-align: right;">0.782609</td>
<td style="text-align: right;">0.666667</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Sfax Ville</td>
<td style="text-align: right;">0.866667</td>
<td style="text-align: right;">0.875</td>
<td style="text-align: right;">0.777778</td>
<td style="text-align: right;">0.928571</td>
<td style="text-align: right;">0.857143</td>
<td style="text-align: right;">0.8125</td>
<td style="text-align: right;">0.6</td>
<td style="text-align: right;">0.923077</td>
<td style="text-align: right;">0.733333</td>
<td style="text-align: right;">0.85</td>
</tr>
<tr class="even">
<td style="text-align: left;">Ettahrir</td>
<td style="text-align: right;">0.928571</td>
<td style="text-align: right;">0.857143</td>
<td style="text-align: right;">0.888889</td>
<td style="text-align: right;">0.818182</td>
<td style="text-align: right;">0.833333</td>
<td style="text-align: right;">0.785714</td>
<td style="text-align: right;">0.882353</td>
<td style="text-align: right;">0.8</td>
<td style="text-align: right;">0.454545</td>
<td style="text-align: right;">0.833333</td>
</tr>
</tbody>
</table>
<p>For the actual optimization, we call the <code>linear_sum_assignment</code> from the module <code>scipy.optimize</code> which applies the Hungarian algorithm to our cost matrix.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">row_ind, col_ind <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> linear_sum_assignment(scores)</span>
<span id="cb6-2"></span>
<span id="cb6-3">scores_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(</span>
<span id="cb6-4">    [</span>
<span id="cb6-5">        {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"source"</span>: NSI_names[i], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"target"</span>: geodata_names[j], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"distance"</span>: scores[i, j]}</span>
<span id="cb6-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(row_ind, col_ind)</span>
<span id="cb6-7">    ]</span>
<span id="cb6-8">).sort_values(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"distance"</span>)</span></code></pre></div></div>
<p>Which gives the correct assignments</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: left;">source</th>
<th style="text-align: left;">target</th>
<th style="text-align: right;">distance</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Ettahrir</td>
<td style="text-align: left;">El Tahrir</td>
<td style="text-align: right;">0.454545</td>
</tr>
<tr class="even">
<td style="text-align: left;">Tina</td>
<td style="text-align: left;">Thyna</td>
<td style="text-align: right;">0.5</td>
</tr>
<tr class="odd">
<td style="text-align: left;">La Medina</td>
<td style="text-align: left;">Médina</td>
<td style="text-align: right;">0.5</td>
</tr>
<tr class="even">
<td style="text-align: left;">Ariana Ville</td>
<td style="text-align: left;">Ariana Médina</td>
<td style="text-align: right;">0.529412</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Souk Lahad</td>
<td style="text-align: left;">Souk El Ahed</td>
<td style="text-align: right;">0.533333</td>
</tr>
<tr class="even">
<td style="text-align: left;">Elksar</td>
<td style="text-align: left;">Ksar</td>
<td style="text-align: right;">0.571429</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Boumhel Bassatine</td>
<td style="text-align: left;">Boumhel</td>
<td style="text-align: right;">0.588235</td>
</tr>
<tr class="even">
<td style="text-align: left;">Sidi Ali Ben Nasrallah</td>
<td style="text-align: left;">Nasrallah</td>
<td style="text-align: right;">0.590909</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Sfax Ville</td>
<td style="text-align: left;">Sfax Médina</td>
<td style="text-align: right;">0.6</td>
</tr>
<tr class="even">
<td style="text-align: left;">Sidi Amor Bou Hajla</td>
<td style="text-align: left;">Bouhajla</td>
<td style="text-align: right;">0.65</td>
</tr>
</tbody>
</table>
</section>
<section id="parting-words" class="level2">
<h2 class="anchored" data-anchor-id="parting-words">Parting words</h2>
<p>This project was truly fun because the actual data collection was not hard but it had enough challenges to keep it interesting. For such a basic project I dealt with extracting data from PDFs, Fuzzy string matching, Optimization algorithms and the final step which is turning the results into an interactive dashboard which you can find <a href="https://share.streamlit.io/iyedg/poverty_rate_dashboard/develop/poverty_rate_dashboard/main.py">here</a>.</p>
<video autoplay="" loop="" muted="" playsinline="" style="width:100%;">
<source src="videos/dashboard.mp4" type="video/mp4">
</video>
<p>For the full code used in this project please visit my Github <a href="https://github.com/iyedg/poverty_rate_dashboard/">repo</a></p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <guid>https://iyedg.com/posts/poverty_rate_tunisia_2020/</guid>
  <pubDate>Fri, 13 Nov 2020 22:00:00 GMT</pubDate>
  <media:content url="https://iyedg.com/posts/poverty_rate_tunisia_2020/featured.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Get started with Plotly Dash: a COVID19 dashboard for Tunisia</title>
  <dc:creator>Iyed Ghedamsi</dc:creator>
  <link>https://iyedg.com/posts/create_covid19_dashbord_plotly_dash/</link>
  <description><![CDATA[ 





<p>Can you create a pretty and usable dashboard without knowing much about frontend development ? Various attempts at making the answer to this question a <code>YES</code> have been made with varying degrees of success. Probably the most famous attempts are tools like PowerBI Microsoft or Tableau which have a relatively low barrier to entry compared to solutions that involve coding. Even the omnipresent <em>(but far form omnipotent)</em> Excel could be used as a dashboarding tool. But that comes at a cost of lower customizability / extensibility. It goes without saying that using these solutions for commercial uses cost vastly more despite having very usable versions for users who wish to try the tools.</p>
<p>In this tutorial we will focus on <a href="https://dash.plotly.com/"><strong>Dash</strong></a> by Plotly, the creators of the <a href="https://github.com/plotly/plotly.py">eponymous plotting library</a>. Keep in mind, however, that the python ecosystem offers a variety of tools with various tradeoffs and considerations. None of these solutions is a cure-all, therefore it is wise to keep an open mind and tinker with some of them <em>(all of them ?)</em>.</p>
<ul>
<li><a href="https://www.streamlit.io/"><strong>Streamlit</strong></a>, <a href="https://www.streamlit.io/gallery">(gallery)</a></li>
<li><a href="https://github.com/voila-dashboards/voila"><strong>Voilà</strong></a>, <a href="https://voila-gallery.org/">(gallery)</a></li>
<li><a href="https://panel.holoviz.org/index.html"><strong>Panel</strong></a>, <a href="https://panel.holoviz.org/index.html">(gallery)</a></li>
<li>Or go full <a href="https://en.wikipedia.org/wiki/Not_invented_here">NIH</a> and build your own with <a href="https://flask.palletsprojects.com/en/1.1.x/"><strong>Flask</strong></a></li>
</ul>
<p>By the end of this tutorial we will have a dashboard that looks like this:</p>
<video controls="" preload="none" style="width:100%;">
<source src="videos/end_result.mp4" type="video/mp4">
</video>
<section id="elements-of-a-plotly-dash-project" class="level2">
<h2 class="anchored" data-anchor-id="elements-of-a-plotly-dash-project">Elements of a <code>Plotly Dash</code> project</h2>
<p>It is important before we start building our dashboard that we understand some concepts driving <strong>Dash</strong>. The first idea we will touch on is <em>reactive programming</em>.</p>
<section id="reactivity-and-callbacks" class="level3">
<h3 class="anchored" data-anchor-id="reactivity-and-callbacks">Reactivity and Callbacks</h3>
<p>Even if you don’t know what <em>reactive programming</em> means you’ve most likely used it in … Excel.</p>
<p>In Excel, when we use a formula to compute the sum of two cells, as soon as a value in the summation changes, the formula cell recomputes its value in reaction.</p>
<figure class="figure">
<video style="width:100%;" id="excel_reactive" autoplay="" muted="" playsinline="" controls="">
<source src="videos/excel_reactive.mp4">
</video>
<figcaption>
<span>Excel is a reactive program</span>
</figcaption>
</figure>
<p>The equivalent idea to an Excel formula for Dash is a callback function.</p>
<div id="e00fc7d6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@app.callback</span>(</span>
<span id="cb1-2">    output<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Output(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ouput-cell"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>),</span>
<span id="cb1-3">    inputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell-1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>), Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell-2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>)],</span>
<span id="cb1-4">)</span>
<span id="cb1-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sum_of_cell1_and_cell2(value_of_cell1, value_of_cell2):</span>
<span id="cb1-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> value_of_cell1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> value_of_cell2</span></code></pre></div></div>
</div>
<p>In the highlighted lines 1-4, we are saying that the attribute <code>value</code> of an object with and ID of <code>output-cell</code> should react to changes in the <code>value</code> attribute of the objects with ID <code>cell-1</code> and <code>cell-2</code>.</p>
<div id="3d9dcde5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@app.callback</span>(</span>
<span id="cb2-2">    output<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Output(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ouput-cell"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>),</span>
<span id="cb2-3">    inputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell-1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>), Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell-2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>)],</span>
<span id="cb2-4">)</span>
<span id="cb2-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sum_of_cell1_and_cell2(value_of_cell1, value_of_cell2):</span>
<span id="cb2-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> value_of_cell1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> value_of_cell2</span></code></pre></div></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://iyedg.com/posts/create_covid19_dashbord_plotly_dash/images/reactivity_callback_chain.webp" class="img-fluid figure-img"></p>
<figcaption>Callbacks diagram</figcaption>
</figure>
</div>
<p>In the function definition we describe how the <code>value</code> attribute of <code>output-cell</code> should react to a change in the <code>value</code> attribute of <code>cell-1</code> and / or <code>cell-2</code>. In our case that would be to return the sum of the values.</p>
<p>It is not important to focus on the syntax for now, we are simply building a conceptual model of how Dash works. One question that arises from the snippet we have just seen is <em>what are</em> <code>output-cell</code>, <code>cell-1</code> <em>and</em> <code>cell-2</code> <em>?</em></p>
</section>
<section id="layout" class="level3">
<h3 class="anchored" data-anchor-id="layout">Layout</h3>
<p>To continue our Excel simile, let us think of an Excel cell as a special kind of user interface components. In essence, a cell in a spredsheet is not that much different from an input box, a checkbox, or a dropdown list. These user interface elements can hold various attributes of their own, including a <code>value</code> attribute, and allow the user to trigger callbacks which ultimately allows our dashboard to <em>react</em> to user input.</p>
<div id="5b9557c2" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dash_core_components <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> dcc</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dash_html_components <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> html</span>
<span id="cb3-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dash</span>
<span id="cb3-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dash.dependencies <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Input, Output</span>
<span id="cb3-5"></span>
<span id="cb3-6">app <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dash.Dash(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>)</span>
<span id="cb3-7"></span>
<span id="cb3-8">app.layout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> html.Div(</span>
<span id="cb3-9">    children<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb3-10">        dcc.Input(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell-1"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"number"</span>, value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>),</span>
<span id="cb3-11">        dcc.Input(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell-2"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"number"</span>, value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb3-12">        html.H1(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"output-cell"</span>),</span>
<span id="cb3-13">    ]</span>
<span id="cb3-14">)</span>
<span id="cb3-15"></span>
<span id="cb3-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@app.callback</span>(</span>
<span id="cb3-17">    output<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Output(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"output-cell"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"children"</span>),</span>
<span id="cb3-18">    inputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell-1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>), Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cell-2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>)],</span>
<span id="cb3-19">)</span>
<span id="cb3-20"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sum_of_cell1_and_cell2(value_of_cell1, value_of_cell2):</span>
<span id="cb3-21">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(value_of_cell1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(value_of_cell2)</span>
<span id="cb3-22"></span>
<span id="cb3-23"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"__main__"</span>:</span>
<span id="cb3-24">    app.run_server(host<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"localhost"</span>, debug<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
</div>
<p>With the addition of a layout as described in the lines 8 through 14, our dashboard can now display a user interface, and react to changes triggered by user input. Running the code above results in the following “<em>dashboard</em>”</p>
<figure class="figure">
<video controls="" autoplay="" muted="" playsinline="" loop="" style="width: 100%;" id="excel_dash">
<source src="videos/excel_dash.mp4" type="video/mp4">
</video>
<figcaption>
<span>First Dash dashboard</span>
</figcaption>
</figure>
</section>
</section>
<section id="getting-our-hands-dirty" class="level2">
<h2 class="anchored" data-anchor-id="getting-our-hands-dirty">Getting our hands dirty</h2>
<video autoplay="" loop="" muted="" playsinline="" style="width:100%; margin: 2em;">
<source src="videos/ghost_in_the_shell.mp4" type="video/mp4">
</video>
<section id="virtual-environment-and-dependencies-installation" class="level3">
<h3 class="anchored" data-anchor-id="virtual-environment-and-dependencies-installation">Virtual environment and dependencies installation</h3>
<p>For this project we will need to install the following dependencies:</p>
<ul>
<li><strong>dash</strong> is the library that will provide two components for our project: the dashboarding and the plotting through <code>plotly-express</code> which we will introduce as we go.</li>
<li><strong>dash-bootstrap-components</strong> will allow us to theme our app using Bootstrap which provides useful layout capabilities and interesting components. For this tutorial we will limit ourselves to using the Grid</li>
<li><strong>pandas</strong> which we will use for the data manipulation part.</li>
<li><strong>geopandas</strong> will be of use when plotting data on a map.</li>
<li><strong>pyprojroot</strong> is a small utility library that allows us to reference files inside our project using paths relative the root of our project instead of absolute <em>long</em> paths.</li>
</ul>
<p>You can install them using the following command</p>
<pre class="shell"><code>pip install dash==1.11.0 dash-bootstrap-components pandas geopandas requests pyprojroot</code></pre>
<p>It is recommended that you create a virtual environment for your project. That can be done easily (assuming you’re running a Unix based system):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">md</span> covid_dash</span>
<span id="cb5-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> covid_dash</span>
<span id="cb5-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">python</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> venv .venv</span>
<span id="cb5-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">source</span> .venv/bin/activate</span></code></pre></div></div>
</section>
<section id="directory-structure" class="level3">
<h3 class="anchored" data-anchor-id="directory-structure">Directory structure</h3>
<p>The directory structure that we will need looks as follows</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">.</span></span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> data</span>
<span id="cb6-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">│</span>  └── raw</span>
<span id="cb6-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└──</span> src</span>
<span id="cb6-5">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> __init__.py</span>
<span id="cb6-6">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> app.py</span>
<span id="cb6-7">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> callbacks.py</span>
<span id="cb6-8">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> cli.py</span>
<span id="cb6-9">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> data.py</span>
<span id="cb6-10">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> index.py</span>
<span id="cb6-11">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> layouts.py</span>
<span id="cb6-12">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└──</span> plots.py</span></code></pre></div></div>
<p>To create it you can run the following commands</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">md</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> plotly_dash_tutorial/<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{data/raw</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">src}</span></span>
<span id="cb7-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> plotly_dash_tutorial</span>
<span id="cb7-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">touch</span> src/__init__.py <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Making a python package named src</span></span>
<span id="cb7-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">touch</span> src/<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{app.py</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">index.py}</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># General application / dashboard code</span></span>
<span id="cb7-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">touch</span> src/<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{callbacks.py</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">layouts.py}</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plotly dash specific code</span></span>
<span id="cb7-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">touch</span> src/<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{plots.py</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data.py}</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The model part of our application</span></span></code></pre></div></div>
</section>
<section id="application-setup" class="level3">
<h3 class="anchored" data-anchor-id="application-setup">Application setup</h3>
<p>To setup our app, we need to create an <code>app</code> object. This object is central to our application in the sense that it acts as the orchestrator of the interaction between our layout components through the callbacks we define.</p>
<p>In addition to creating a Dash <code>app</code> object, we pass style information through the <code>external_stylesheets</code> key word.</p>
<p><strong>app.py</strong></p>
<div id="b368df3d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dash</span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dash_bootstrap_components <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> dbc</span>
<span id="cb8-4"></span>
<span id="cb8-5">app <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dash.Dash(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>, external_stylesheets<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[dbc.themes.YETI, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"custom.css"</span>])</span></code></pre></div></div>
</div>
<p><code>index.py</code> will act as the entry point to our dashboard. The lines 7-8 allow python to call the <code>run_server</code> method from our Dash <code>app</code> object if <code>index.py</code> is called from the command line. The key word <code>debug</code> provides us with autoreload and more expressive UI side error, therefore when developing a dashboard it is recommended that it be set to True.</p>
<p>You may notice that we’ve only used two of our imports in the body of <code>index.py</code>. We used the app to start a server for our dashboard, and use the layout import to attach it to our <code>app</code> object, what about <code>callbacks</code> ? One may be inclined to remove the line importing <code>callbacks</code> but that would mean that our app will not have access to any logic we define in our callbacks.</p>
<p><strong>index.py</strong></p>
<div id="cc44fe9b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> . <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> callbacks</span>
<span id="cb9-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> .app <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> app</span>
<span id="cb9-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> .layouts <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> layout</span>
<span id="cb9-4"></span>
<span id="cb9-5">app.layout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> layout</span>
<span id="cb9-6"></span>
<span id="cb9-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"__main__"</span>:</span>
<span id="cb9-8">    app.run_server(host<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"localhost"</span>, debug<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
</div>
</section>
<section id="creating-the-layout" class="level3">
<h3 class="anchored" data-anchor-id="creating-the-layout">Creating the layout</h3>
<p><strong>layouts.py</strong></p>
<div id="00485cd8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dash_bootstrap_components <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> dbc</span>
<span id="cb10-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dash_core_components <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> dcc</span>
<span id="cb10-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dash_html_components <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> html</span></code></pre></div></div>
</div>
<p>Let’s begin by discussing the imported modules for <code>layouts.py</code>. <code>dash_bootstrap_components</code>, <code>dash_core_components</code> and <code>dash_html_components</code> contain components which correspond to HTML elements. These are what largely liberates the developers from actually writing HTML, CSS which are responsible for the View layer of our dashboard. The components provided by these modules can vary in complexity from being a mere text container such as <code>html.H1</code> to a full interactive table such as <code>dcc.DataTable</code>. It is generally useful to keep the documentation from theses modules open in a side tab while creating the dashboard.</p>
<p>The general layout of our page is composed of two major containers, a sidebar and a main content area.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://iyedg.com/posts/create_covid19_dashbord_plotly_dash/images/Base layout.webp" class="img-fluid figure-img"></p>
<figcaption>Base layout</figcaption>
</figure>
</div>
<p>Our main container uses the self-descriptive component <code>bcc.Container</code>. It is, however, important that we understand that despite this component and similar <em>layout</em> components, do not translate directly into visible elements on our page, they modify the <em>position</em> of elements on the page. In addition, the <code>Container</code> component comes with the added benefit of adding <em>responsivity</em> to our page thanks to being based on Bootstrap, which further improves the usability of our dashboard.</p>
<p>As a rule of thumb, components from <code>dash_html_components</code> correspond to HTML elements, and they are named as such. For instance, an <code>h1</code> element in raw HTML corresponds to <code>html.H1</code> <em>(notice the capitalization)</em>. By contrast, components from <code>dash_core_components</code> contain components with interactivity baked into them such as tabs, dropdown lists and data tables.</p>
<p><strong>layouts.py</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">SIDEBAR_STYLE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb11-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"position"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fixed"</span>,</span>
<span id="cb11-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb11-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"left"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb11-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb11-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"width"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"18rem"</span>,</span>
<span id="cb11-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"padding"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2rem 1rem"</span>,</span>
<span id="cb11-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"background-color"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#f8f9fa"</span>,</span>
<span id="cb11-9">}</span>
<span id="cb11-10"></span>
<span id="cb11-11">MAIN_CONTAINER_STYLE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb11-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"margin-left"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"18rem"</span>,</span>
<span id="cb11-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"margin-right"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2rem"</span>,</span>
<span id="cb11-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"padding"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2rem 1rem"</span>,</span>
<span id="cb11-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"height"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"100vh"</span>,</span>
<span id="cb11-16">}</span>
<span id="cb11-17"></span>
<span id="cb11-18">sidebar <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> html.Div(</span>
<span id="cb11-19">    [</span>
<span id="cb11-20">        html.H3(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"COVID19 dashboard for cases in Tunisia"</span>),</span>
<span id="cb11-21">        html.Hr(),</span>
<span id="cb11-22">    ],</span>
<span id="cb11-23">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>SIDEBAR_STYLE,</span>
<span id="cb11-24">)</span>
<span id="cb11-25"></span>
<span id="cb11-26">main_container <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dbc.Container(</span>
<span id="cb11-27">    [</span>
<span id="cb11-28">        dcc.Loading(</span>
<span id="cb11-29">            dcc.Graph(</span>
<span id="cb11-30">                <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"main_graph"</span>,</span>
<span id="cb11-31">                figure<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>figure,</span>
<span id="cb11-32">            )</span>
<span id="cb11-33">        ),</span>
<span id="cb11-34">    ],</span>
<span id="cb11-35">    style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>MAIN_CONTAINER_STYLE,</span>
<span id="cb11-36">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"main_container"</span>,</span>
<span id="cb11-37">)</span>
<span id="cb11-38"></span>
<span id="cb11-39">layout <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dbc.Container([sidebar, main_container], fluid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
<p>As for the dictionaries <code>SIDEBAR_STYLE</code> and <code>MAIN_CONTENT_STYLE</code> they are used to show that there are multiple ways to define the style and layout of our components. In both cases, we must provide valid CSS rules. Dictionaries of style may be useful when we have a style rule specific to a component or simply as a shorthand for writing an external CSS stylesheet.</p>
<p>It is also worth noting that we must assign and <code>id</code> to each component we will interact with later on in our callbacks.</p>
<p><strong>layouts.py</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"main_container"</span></span></code></pre></div></div>
<p>Finally, we define our root container and simply set <code>sidebar</code> and <code>main_container</code> as its children.</p>
<p>Now we will go over the specific components that we will use in this dashboard:</p>
<section id="dcc.radioitems" class="level4">
<h4 class="anchored" data-anchor-id="dcc.radioitems"><code>dcc.RadioItems</code></h4>
<p>Radio Items are generally used in groups where the user must choose exactly one option, and must choose an option. To this end, we will use the <code>dcc.RadioItems</code> component to get let the user choose the data view they want displayd in the main container area of our page. We will have three options:</p>
<ul>
<li>Map view</li>
<li>Line chart view</li>
<li>Bar race chart view</li>
</ul>
<p>To implement this use case in Dash, we write the following code:</p>
<p><strong>layouts.py</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">view_selector <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> html.Div(</span>
<span id="cb13-2">    [</span>
<span id="cb13-3">        html.H4(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dashboard view"</span>),</span>
<span id="cb13-4">        dcc.RadioItems(</span>
<span id="cb13-5">            <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content_view_selector"</span>,</span>
<span id="cb13-6">            options<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb13-7">                {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"label"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Map view"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"map"</span>},</span>
<span id="cb13-8">                {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"label"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Line chart view"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"line"</span>},</span>
<span id="cb13-9">                {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"label"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bar race chart view"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bar_race"</span>},</span>
<span id="cb13-10">            ],</span>
<span id="cb13-11">            value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"map"</span>,</span>
<span id="cb13-12">            labelStyle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"display"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"block"</span>},</span>
<span id="cb13-13">        ),</span>
<span id="cb13-14">    ]</span>
<span id="cb13-15">)</span></code></pre></div></div>
<p>Essentially, the <code>RadioItems</code> components takes a list of dictionaries as <code>options</code>. Each dictionary must have at least the two keys <code>label</code> and <code>value</code>. The label of the option is the text that will be shown on the user interface, while <code>value</code> is a corresponding alias that we use internally in our code, which means it is possible to have the label and the value be the same string. The <code>value</code> key word provides the default value of our component.</p>
<p>As we mentioned before, since we will be interacting with this component, we must give it an id, <code>content_view_selector</code> in this specific case.</p>
</section>
<section id="dcc.dropdown" class="level4">
<h4 class="anchored" data-anchor-id="dcc.dropdown"><code>dcc.Dropdown</code></h4>
<p>Dropdown lists are very similar to a Radio Items group in that they allow the user to pick choice(s) from a list of possible options. The difference, despite being subtle, is rather important: Dropdown lists <em>may</em> allow a user to pick more than one choice. In addition, on a user experience level, dropdown lists are usually reserved for longer lists of options as a means to declutter our interface. In our specific case we could have used another Radio Items group but the dropdown list is used merely to illustrate another component.</p>
<p>Notice that in this instance we assign the options keys <code>label</code> and <code>value</code> the same text out of a list of possible choices <code>by_gov_indicators</code>. This pattern can be useful when the text to display and the internal value used in the code do not differ.</p>
<p>We set the key word <code>clearable</code> to False to force the component to always have a value that is not <code>NULL</code>.</p>
<p><strong>layouts.py</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">indicator_selector <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> html.Div(</span>
<span id="cb14-2">    [</span>
<span id="cb14-3">        html.H4(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Indicator"</span>),</span>
<span id="cb14-4">        dcc.Dropdown(</span>
<span id="cb14-5">            <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"indicator_selector"</span>,</span>
<span id="cb14-6">            options<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb14-7">                {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"label"</span>: indicator, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>: indicator}</span>
<span id="cb14-8">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> indicator <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> by_gov_indicators</span>
<span id="cb14-9">            ],</span>
<span id="cb14-10">            value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>by_gov_indicators[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb14-11">            clearable<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>,</span>
<span id="cb14-12">        ),</span>
<span id="cb14-13">    ]</span>
<span id="cb14-14">)</span></code></pre></div></div>
</section>
<section id="dcc.graph" class="level4">
<h4 class="anchored" data-anchor-id="dcc.graph"><code>dcc.Graph</code></h4>
<p>Now we address the most important component of our Dashboard, in terms of real estate on the screen and in terms of value: the <code>dcc.Graph</code>.</p>
<p><strong>layouts.py</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1">dcc.Graph(</span>
<span id="cb15-2">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"main_graph"</span>,</span>
<span id="cb15-3">    figure<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>figure,</span>
<span id="cb15-4">)</span></code></pre></div></div>
<p>That’s it !</p>
<p>The graph component does not take any fiddling around. In the general case we will just provide it with a <code>Figure</code> object from <code>plotly.express</code> or <code>plotly.graph_objects</code> or even nested python dictionaries describing the figure.</p>
<p>Now our Interface should look somehting like this:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://iyedg.com/posts/create_covid19_dashbord_plotly_dash/images/finished_layout.webp" class="img-fluid figure-img"></p>
<figcaption>Finished layout</figcaption>
</figure>
</div>
</section>
<section id="callbacks-reacting-to-user-input" class="level4">
<h4 class="anchored" data-anchor-id="callbacks-reacting-to-user-input">Callbacks: reacting to user input</h4>
<p>If we were to run our dashboard as it is now, we would be greeted with a well laid out set of components on a page that do nothing. The missing ingredient is callbacks.</p>
<p><strong>callbacks.py</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dash.dependencies <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Input, Output</span>
<span id="cb16-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> .app <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> app</span>
<span id="cb16-3"></span>
<span id="cb16-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> .plots <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> (</span>
<span id="cb16-5">    plot_daily_cumulative_active_cases,</span>
<span id="cb16-6">    plot_part_of_daily_active_cases,</span>
<span id="cb16-7">    plot_race_plot_of_cumulative_daily_active_cases,</span>
<span id="cb16-8">)</span>
<span id="cb16-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> .data <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> geo_targa_covid_df</span>
<span id="cb16-10"></span>
<span id="cb16-11"></span>
<span id="cb16-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@app.callback</span>(</span>
<span id="cb16-13">    Output(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"main_graph"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"figure"</span>),</span>
<span id="cb16-14">    [Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content_view_selector"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>), Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"indicator_selector"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>)],</span>
<span id="cb16-15">)</span>
<span id="cb16-16"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> update_main_content(view, indicator):</span>
<span id="cb16-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> view <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"map"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> view <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb16-18">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> plot_part_of_daily_active_cases(geo_targa_covid_df, indicator)</span>
<span id="cb16-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> view <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"line"</span>:</span>
<span id="cb16-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> plot_daily_cumulative_active_cases(geo_targa_covid_df, indicator)</span>
<span id="cb16-21">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb16-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> plot_race_plot_of_cumulative_daily_active_cases(</span>
<span id="cb16-23">            geo_targa_covid_df, indicator</span>
<span id="cb16-24">        )</span></code></pre></div></div>
<p>As can be seen, <code>callbacks.py</code> does not contain much code, so let us dissect it bit by bit.</p>
<p><strong>callbacks.py</strong></p>
<div id="ce8fe93b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dash.dependencies <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Input, Output</span>
<span id="cb17-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> .app <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> app</span></code></pre></div></div>
</div>
<p>In the first line, we import <code>Input</code> and <code>Output</code> which are functions that allow us to define the direction of the flow of information in our app. Then we import the <code>app</code> object as it will be used to define the callback functions later.</p>
<p><code>Input</code> and <code>Output</code> have a similar function signature; both of them take two arguments: <code>component_id</code> and <code>component_property</code>. These information allow Dash to build a dependency tree between the various properties of the components that we use in our callbacks. In our case, when we set the <code>Output</code> of our callback function <code>update_main_content</code> to the <code>figure</code> property of <code>main_graph</code>, we are describing a flow of information from the inputs of our callback function: the <code>value</code> property of <code>content_view_selector</code> and <code>indicator_selector</code>, through the body of our callback function where we transform and / or augment the values we’ve received, and returing the information that changes the <code>figure</code> property of <code>main_graph</code>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://iyedg.com/posts/create_covid19_dashbord_plotly_dash/images/final_callback_chain.webp" class="img-fluid figure-img"></p>
<figcaption>Final dashboard callback chain</figcaption>
</figure>
</div>
<p>To understand the specific flow in information in our callback, let us look back at the main body of the callback function:</p>
<p><strong>callbacks.py</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@app.callback</span>(</span>
<span id="cb18-2">    Output(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"main_graph"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"figure"</span>),</span>
<span id="cb18-3">    [Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content_view_selector"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>), Input(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"indicator_selector"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>)],</span>
<span id="cb18-4">)</span>
<span id="cb18-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> update_main_content(view, indicator):</span>
<span id="cb18-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> view <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"map"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> view <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb18-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> plot_part_of_daily_active_cases(geo_targa_covid_df, indicator)</span>
<span id="cb18-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> view <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"line"</span>:</span>
<span id="cb18-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> plot_daily_cumulative_active_cases(geo_targa_covid_df, indicator)</span>
<span id="cb18-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb18-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> plot_race_plot_of_cumulative_daily_active_cases(</span>
<span id="cb18-12">            geo_targa_covid_df, indicator</span>
<span id="cb18-13">        )</span></code></pre></div></div>
<p>Firstly, you should notice the order of the arguments of our function: <code>view</code> then <code>indicator</code>. This order corresponds to the order in which we declared our dependent inputs when calling <code>@app.callback</code>.</p>
<blockquote class="blockquote">
<p>A Dash callback function takes only positional arguments whose order corresponds to the order of <code>Inputs</code> <small><em>and <code>states</code> also but that’s another topic</em></small>.</p>
</blockquote>
</section>
<section id="general-application-files" class="level4">
<h4 class="anchored" data-anchor-id="general-application-files">General application files</h4>
<p>In <code>callbacks.py</code> we imported objects from two modules: <code>data</code> and <code>plots</code>. I have created these two modules primarily to declutter the <code>callbacks.py</code> and <code>layouts.py</code> files. But it is also a good practice following the <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">Don’t repeat yourself Principle (<strong>DRY</strong>)</a> as well as <a href="https://en.wikipedia.org/wiki/Separation_of_concerns">Separation of Concerns (<strong>SoC</strong>)</a>. By using a module where I include all the steps of data preparation, and another where I include all the code necessary for generating my plots, I am avoiding creating a huge cluster of code that is less maintainable and a headache to extend and / or refactor.</p>
<blockquote class="blockquote">
<p>To see how the data was prepared please refer to <a href="https://nbviewer.jupyter.org/github/iyedg/iyedg.github.io/blob/develop/content/post/create_covid19_dashbord_plotly_dash/notebooks/01_data_preparation.ipynb">this notebook</a> and to <a href="https://github.com/iyedg/plotly_dash_tutorial_code/blob/master/src/data.py">data.py</a></p>
</blockquote>
</section>
</section>
</section>
<section id="parting-thoughts" class="level2">
<h2 class="anchored" data-anchor-id="parting-thoughts">Parting thoughts</h2>
<p>The creation of dashboards with a tool such as Plotly Dash is definitely much more involved that its WYSIWYG counterparts. However I found through my experience with making dashboards that with a correct assessment of the needs, choosing to code your own dashboard may prove a vastly more pleasurable experience both in creating and in maintaining it. As Abraham Maslow once wrote</p>
<blockquote class="blockquote">
<p>If all you have is a hammer, everything looks like a nail<sup>1</sup></p>
</blockquote>
<p>Tools like Dash should not be used as a cure-all solution, but neither should Excel or Tableau. That is why the more tools in your toolbelts, the less effort you will spend hammering nails.</p>
</section>
<section id="further-reading" class="level2">
<h2 class="anchored" data-anchor-id="further-reading">Further reading</h2>
<ul>
<li><a href="https://dash.plotly.com/urls">Official documentation on multi-page apps</a></li>
<li><a href="https://pbpython.com/plotly-dash-intro.html">Practical Business Python - Creating Interactive Visualizations with Plotly’s Dash Framework</a> <strong>(I recommend this blog in general not just this post)</strong></li>
<li><a href="https://aatishb.com/covidtrends/">An awesome example of a more developed COVID-19 dashboard built with Plotly Dash</a></li>
</ul>


</section>


<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a><div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p><a href="https://en.wiktionary.org/wiki/if_all_you_have_is_a_hammer,_everything_looks_like_a_nail" class="uri">https://en.wiktionary.org/wiki/if_all_you_have_is_a_hammer,_everything_looks_like_a_nail</a>↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>plotly</category>
  <category>python</category>
  <category>dashboards</category>
  <guid>https://iyedg.com/posts/create_covid19_dashbord_plotly_dash/</guid>
  <pubDate>Fri, 01 May 2020 21:00:00 GMT</pubDate>
</item>
</channel>
</rss>
