<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Bar Plot on David Davó&#39;s dev log</title>
    <link>https://blog.ddavo.me/tags/bar-plot/</link>
    <description>Recent content in Bar Plot on David Davó&#39;s dev log</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>© David Davó 2015 - 2024</copyright>
    <lastBuildDate>Wed, 22 May 2024 18:27:50 +0000</lastBuildDate><atom:link href="https://blog.ddavo.me/tags/bar-plot/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Less confusing confusion matrices with Seaborn</title>
      <link>https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/</link>
      <pubDate>Wed, 22 May 2024 18:27:50 +0000</pubDate>
      
      <guid>https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/</guid>
      <description>In this post I use a JointGrid with bar plots to make confusion matrices less confusing</description>
      <content:encoded><![CDATA[<p>The other day my supervisor gave me an interesting paper to read on data visualization: <a href="https://dl.acm.org/doi/pdf/10.1145/3415224">Designing Alternative Representations of Confusion
Matrices to Support Non-Expert Public Understanding of
Algorithm Performance</a> (full reference below, on <em>further reading</em>).</p>
<p>In case you don&rsquo;t know what a confusion matrix is, is a tool that we use in machine learning to visualize the performance of a classification algorithm.</p>
<p>This kind of algorithms have some data, that can be in some class or not, and try to predict whether new data is in that class or not. For example, let&rsquo;s say we have a model that classifies incoming mail as spam or not, we can use a confusion matrix to visualize how our original data is classified.</p>
<p>The confusion matrix is a contingency table of the training data with two dimensions: <em>actual</em> and <em>predicted</em>, i.e.: a 2x2 table with every possibility of correct prediction, incorrect prediction, actually in that class, and actually not in that class.</p>
<p>To facilitate its visualization, this table is usually coloured as a <em>heatmap</em>, where every square has a colour representing the &ldquo;strength&rdquo; of the value.</p>
<figure>
        <img loading="lazy" srcset="https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/heatmap_hub7946e53d5e4abb803b2de6ac2038caf_15785_360x0_resize_box_3.png 360w ,https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/heatmap_hub7946e53d5e4abb803b2de6ac2038caf_15785_480x0_resize_box_3.png 480w ,https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/heatmap.png 640w" 
            sizes="(min-width: 768px) 720px, 100vw" src="https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/heatmap.png" alt="A sample confusion matrix with 47 true positives, 22 true negatives" 
            width="640" height="480"><figcaption>
            <p>A sample confusion matrix with 47 True Positives and 22 True Negatives (69 correct predictions) and 9 incorrect predictions</p>
        </figcaption>
</figure>

<p><strong>Nevertheless, all of this can be difficult to understand at a glance for people who are not into Machine Learning</strong>, and that&rsquo;s why Shen et. al explored those alternatives.</p>
<h2 id="using-bar-charts">Using bar charts</h2>
<p>In the previously mentioned research paper, Hong et al. explore different representations of the same data and how they are understood by non-experts. From the results of their experiment, we can conclude that using a flow chart is the best way to make users who are not familiar with these plots understand them. Nevertheless, bar charts are better for <em>simulating</em> in your head, i.e.: calculating where a certain case will fall in the classes.</p>
<p>Furthermore, bar charts are easier to code and take up less space, so we decided to use them for a technical audience who might not be familiar with confusion matrices but surely is familiar with bar charts.</p>
<figure>
        <img loading="lazy" srcset="https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/bars_hu062e503f807a7637a445da63ab0451cd_16724_360x0_resize_box_3.png 360w ,https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/bars.png 400w" 
            sizes="(min-width: 768px) 720px, 100vw" src="https://blog.ddavo.me/posts/tutorials/confusing-confusion-matrices-seaborn/bars.png" alt="A sample confusion matrix with 47 true positives and 22 true falses" 
            width="400" height="400"><figcaption>
            <p>The same data, but with another way of displaying it</p>
        </figcaption>
</figure>

<p>This figure highlights how there is a lot more spam than ham (non-spam).</p>
<p>Finally, without further ado, the Python code used to create this plot is:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">_palette</span> <span class="o">=</span> <span class="n">sns</span><span class="o">.</span><span class="n">colour_palette</span><span class="p">(</span><span class="s1">&#39;Paired&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">_total</span> <span class="o">=</span> <span class="n">_toplot</span><span class="p">[</span><span class="s1">&#39;count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">sum</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">_max</span> <span class="o">=</span> <span class="n">_toplot</span><span class="p">[</span><span class="s1">&#39;count&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">max</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">_toplot</span><span class="p">[</span><span class="s1">&#39;pct&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">_toplot</span><span class="p">[</span><span class="s1">&#39;count&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="n">_total</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">_toplot</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Total:&#34;</span><span class="p">,</span> <span class="n">_total</span><span class="p">,</span> <span class="s2">&#34;max:&#34;</span><span class="p">,</span> <span class="n">_max</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">sns</span><span class="o">.</span><span class="n">axes_style</span><span class="p">(</span><span class="s2">&#34;white&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Get the colour map</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># https://stackoverflow.com/a/38575399/4505998</span>
</span></span><span class="line"><span class="cl">    <span class="n">g</span> <span class="o">=</span> <span class="n">sns</span><span class="o">.</span><span class="n">catplot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">data</span><span class="o">=</span><span class="n">_toplot</span><span class="o">.</span><span class="n">reset_index</span><span class="p">(),</span> <span class="n">y</span><span class="o">=</span><span class="s1">&#39;count&#39;</span><span class="p">,</span> <span class="n">col</span><span class="o">=</span><span class="s1">&#39;Predicted&#39;</span><span class="p">,</span> <span class="n">row</span><span class="o">=</span><span class="s1">&#39;Actual&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">kind</span><span class="o">=</span><span class="s1">&#39;bar&#39;</span><span class="p">,</span> <span class="n">height</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">margin_titles</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">palette</span><span class="o">=</span><span class="n">_palette</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">g</span><span class="o">.</span><span class="n">set</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Set the ylim to the 120% to leave some space for letters</span>
</span></span><span class="line"><span class="cl">    <span class="n">ylim</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">_max</span><span class="o">*</span><span class="mf">1.2</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Remove left ticks (redundant)</span>
</span></span><span class="line"><span class="cl">    <span class="n">yticks</span><span class="o">=</span><span class="p">[],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Setting the titles</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">ax</span><span class="p">,</span><span class="n">l</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">g</span><span class="o">.</span><span class="n">axes</span><span class="p">[:,</span><span class="mi">0</span><span class="p">],</span><span class="n">g</span><span class="o">.</span><span class="n">row_names</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">g</span><span class="o">.</span><span class="n">set_titles</span><span class="p">(</span><span class="n">col_template</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">{col_name}</span><span class="s2">&#34;</span><span class="p">,</span> <span class="n">row_template</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Making it more beautiful</span>
</span></span><span class="line"><span class="cl"><span class="n">g</span><span class="o">.</span><span class="n">despine</span><span class="p">(</span><span class="n">left</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">colours</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">ax</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">g</span><span class="o">.</span><span class="n">axes</span><span class="o">.</span><span class="n">ravel</span><span class="p">()):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Setting the bar labels</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Display the number and percentage of proposals in each class</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">ax</span><span class="o">.</span><span class="n">containers</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">labels</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">v</span><span class="o">.</span><span class="n">get_height</span><span class="p">()</span><span class="si">:</span><span class="s1">.0f</span><span class="si">}</span><span class="s1"> (</span><span class="si">{</span><span class="n">v</span><span class="o">.</span><span class="n">get_height</span><span class="p">()</span><span class="o">/</span><span class="n">_total</span><span class="o">*</span><span class="mi">100</span><span class="si">:</span><span class="s1">.1f</span><span class="si">}</span><span class="s1">%)&#39;</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">c</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">bar_label</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">labels</span><span class="o">=</span><span class="n">labels</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1"># Set the colour of each bar to a colourmap</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># plt.setp(b, colour=_cmap(b.get_height() / _max))</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># plt.setp(b, colour=_cmap(b.get_height() / _total))</span>
</span></span><span class="line"><span class="cl">            <span class="n">plt</span><span class="o">.</span><span class="n">setp</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">colour</span><span class="o">=</span><span class="n">_palette</span><span class="p">[</span><span class="n">colours</span><span class="p">[</span><span class="n">i</span><span class="p">]])</span>
</span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">savefig</span><span class="p">(</span><span class="s2">&#34;bars.png&#34;</span><span class="p">)</span>
</span></span></code></pre></div><h2 id="references-and-further-reading">References and Further reading</h2>
<ul>
<li>Complete code with imports on <a href="https://www.kaggle.com/code/daviddavo/blog-less-confusing-confusion-matrices">Kaggle</a></li>
<li>Hong Shen, Haojian Jin, Ángel Alexander Cabrera, Adam Perer, Haiyi Zhu, and Jason I. Hong. 2020. <em>Designing Alternative Representations of Confusion Matrices to Support Non-Expert Public Understanding of Algorithm Performance.</em> Proc. ACM Hum.-Comput. Interact. 4, CSCW2, Article 153 (October 2020), 22 pages. <a href="https://doi.org/10.1145/3415224">https://doi.org/10.1145/3415224</a></li>
<li><a href="https://en.wikipedia.org/wiki/Confusion_matrix">Confusion Matrix - Wikipedia</a></li>
</ul>
<p>Finally, if you liked this post, you might like other posts about data visualization like <a href="https://blog.ddavo.me/posts/tutorials/seaborn-heatmap-marginal-distribution/">Creating a HeatMap with marginal distributions using Seaborn</a></p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
