<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title></title>
      <link>https://mzdravkov.com</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://mzdravkov.com/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Wed, 19 Mar 2025 00:00:00 +0000</lastBuildDate>
      <item>
          <title>UpSet plot in Julia with Makie</title>
          <pubDate>Wed, 19 Mar 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://mzdravkov.com/blog/julia-upset-plot/</link>
          <guid>https://mzdravkov.com/blog/julia-upset-plot/</guid>
          <description xml:base="https://mzdravkov.com/blog/julia-upset-plot/">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;UpSet_plot&quot;&gt;UpSet plots&lt;&#x2F;a&gt; are a data visualization method that is used to show multiple intersecting sets. Conceptually, they provide similar information as a Venn diagram, but can be easier to comprehend when the number of sets is higher. Additionally, they provide the ability to show additional attributes of the sets. Here we&#x27;ll implement a simple UpSet plot in &lt;a href=&quot;https:&#x2F;&#x2F;julialang.org&quot;&gt;Julia&lt;&#x2F;a&gt; using &lt;a href=&quot;https:&#x2F;&#x2F;makie.org&#x2F;&quot;&gt;Makie&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll use CairoMakie, which can be used to render plots as SVG or PNG images. Additionally, we&#x27;ll use the &lt;a href=&quot;https:&#x2F;&#x2F;juliapackages.com&#x2F;p&#x2F;Combinatorics&quot;&gt;Combinatorics&lt;&#x2F;a&gt; package to get all possible combinations of the provided sets. First, make sure you have the necessary dependencies installed:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;julia&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-julia &quot;&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span&gt; Pkg
&lt;&#x2F;span&gt;&lt;span&gt;Pkg.add(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;CairoMakie&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;Pkg.add(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Combinatorics&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we can add the packages to our namespace:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;julia&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-julia &quot;&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span&gt; CairoMakie
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span&gt; Combinatorics
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The data for UpSet plots can come in various ways. Our function will use the following format as its main input:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;julia&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-julia &quot;&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# The keys of the dictionary represent the combinations of
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# the sets we want to visualize and the values are the number
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# of elements common to all sets of the corresponding key.
&lt;&#x2F;span&gt;&lt;span&gt;data = Dict(
&lt;&#x2F;span&gt;&lt;span&gt;  [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;93&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;123&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;27&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;33&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For example, in the data above we have indicated that we have &lt;em&gt;100&lt;&#x2F;em&gt; elements in set &lt;strong&gt;a&lt;&#x2F;strong&gt; and &lt;em&gt;93&lt;&#x2F;em&gt; in set &lt;strong&gt;b&lt;&#x2F;strong&gt;, while the intersection between them contains &lt;em&gt;27&lt;&#x2F;em&gt; elements.&lt;&#x2F;p&gt;
&lt;p&gt;We also will provide a vector of the base sets to the function, so that we can control the order in which they&#x27;re shown:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;julia&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-julia &quot;&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span&gt;order = [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, a basic UpSet plot can be accomplished with a function such as this one:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;julia&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-julia &quot;&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;upset&lt;&#x2F;span&gt;&lt;span&gt;(data, order)
&lt;&#x2F;span&gt;&lt;span&gt;  fig = Figure()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  num_sets = length(order)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# top is the barplot part of the UpSet.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# bottom is the part that shows the set intersections.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# We reverse the given order, because we want the
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# first given set to be at the top (highest y-value).
&lt;&#x2F;span&gt;&lt;span&gt;  top = Axis(fig[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;  bottom = Axis(fig[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;                yticks = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:num_sets, reverse(order)))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# We get all possible combinations, not just
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# the ones that were given in the input data.
&lt;&#x2F;span&gt;&lt;span&gt;  combs = collect(combinations(order))
&lt;&#x2F;span&gt;&lt;span&gt;  num_combs = length(combs)
&lt;&#x2F;span&gt;&lt;span&gt;  comb_counts = map(c -&amp;gt; get(data, c, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;), combs)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  set_index = Dict(zip(order, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:num_sets))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  barplot!(top, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:num_combs, comb_counts, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;:black&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, comb) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; enumerate(combs)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# For each combination we get the row positions of the
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# top and bottom sets. We use this information to plot
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# lines that connect the dots that represent the sets.
&lt;&#x2F;span&gt;&lt;span&gt;    min_y = min(map(s -&amp;gt; set_index[s], comb)...)
&lt;&#x2F;span&gt;&lt;span&gt;    max_y = max(map(s -&amp;gt; set_index[s], comb)...)
&lt;&#x2F;span&gt;&lt;span&gt;    lines!(bottom, [i, i], [num_sets - min_y + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, num_sets - max_y + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;], color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;:gray&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# We plot as large dots all the sets in the current combination.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; set &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; comb
&lt;&#x2F;span&gt;&lt;span&gt;      scatter!(bottom, i, num_sets - set_index[set] + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, markersize=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;15&lt;&#x2F;span&gt;&lt;span&gt;, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;:black&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  xlims!(top, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;, num_combs+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  xlims!(bottom, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;, num_combs+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  hidexdecorations!(top)
&lt;&#x2F;span&gt;&lt;span&gt;  hidexdecorations!(bottom)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  linkxaxes!(top, bottom)
&lt;&#x2F;span&gt;&lt;span&gt;  hidespines!(top)
&lt;&#x2F;span&gt;&lt;span&gt;  hidespines!(bottom)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# This controls the relative height of the two rows.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# This would make a fine additional parameter for our
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# function so that we can easily tweak it, depending
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# on the number of sets we want to plot.
&lt;&#x2F;span&gt;&lt;span&gt;  rowsize!(fig.layout, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, Relative(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;  rowsize!(fig.layout, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, Relative(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  fig
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, we can run the function and obtain an UpSet plot:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;julia&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-julia &quot;&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span&gt;fig = upset(data, order)
&lt;&#x2F;span&gt;&lt;span&gt;save(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;upset_plot.png&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, fig)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which produces the following plot:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;upset_plot.png&quot; alt=&quot;UpSet plot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
