Python Dash vs. R Shiny - Which To Choose in 2021 and Beyond

Estimated time:

<span data-preserver-spaces="true">Developing dashboards is no small task. You have to think about a vast amount of technical details and at the same time build something easy and enjoyable to use. </span><span data-preserver-spaces="true">Let's say you have those areas covered. The question remains - which technology should you use? <strong>R</strong> or <strong>Python</strong>? <strong>Dash</strong> vs. <strong>Shiny</strong>?</span>

<span data-preserver-spaces="true">Today we'll compare two technologies for building <strong>web applications</strong> - Python Dash and <a href="" target="_blank" rel="noopener noreferrer">R Shiny</a>. After reading, you'll know how these two <strong>compare</strong> and when it's better to use one over the other. You'll also see if it's worth it to make a long-term switch to either. </span>For a truly immersive face-off experience, download the <a href="">source code</a> of the sample dashboard used to illustrate Dash and Shiny <strong>capabilities</strong>.

In 2022, Posit announced <strong>Shiny for Python</strong>. It's still in alpha, but if you're curious to test it, follow our <a href="" target="_blank" rel="noopener">tutorial on PyShiny</a>. We don't recommend using PyShiny (Shiny for Python) for production yet, but as it evolves we will share our thoughts and knowledge on when and how you can use it. Stay tuned!

<strong>Updated</strong>: March 1, 2022.
<ul><li><a href="#overview">Library Overview</a></li><li><a href="#boilerplate">Which Requires More Boilerplate Code?</a></li><li><a href="#ui">How to Create UI Elements</a></li><li><a href="#styling-ui-1">How to Style UI with CSS</a></li><li><a href="#styling-ui-2">How to Style UI with Bootstrap</a></li><li><a href="#reactivity">Reactivity</a></li><li><a href="#publishing">Publishing and Deployment</a></li><li><a href="#anchor-7">Python Dash vs. R Shiny: final face-off</a></li></ul>

<hr />

<span data-preserver-spaces="true">At </span><a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Appsilon</span></a><span data-preserver-spaces="true">, we are global leaders in R Shiny and we've developed some of the world's most </span><a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">advanced R Shiny dashboards</span></a><span data-preserver-spaces="true">, so we have a natural bias toward using Shiny. Still, we'll do our best to provide an honest and unbiased opinion in this article. We're not going to throw arbitrary points to Shiny just because we prefer it for <a href="" target="_blank" rel="noopener noreferrer">enterprise app development</a>.</span>

<span data-preserver-spaces="true">It's also worth noting that whether you choose Dash or Shiny (or both!), you can deploy your apps through <a href="" target="_blank" rel="noopener noreferrer">RStudio Connect</a>. With Connect, you can now share Flask APIs and interactive dashboards written in both R and Python. Appsilon is a <a href="" target="_blank" rel="noopener noreferrer">Full-Service Certified RStudio Partner</a> and can assist with deployment and <a href="" target="_blank" rel="noopener noreferrer">app scaling</a> regardless of your choice of the underlying technology.</span>
<h2 id="overview"><span data-preserver-spaces="true">Library Overview for Dash and Shiny</span></h2>
<span data-preserver-spaces="true">Let's start with Dash. It is a Python framework used for building web applications. It's written in Flask, Plotly.js, and React.js, so it's an ideal candidate for creating dashboards. If you're a heavy Python user, Dash allows you to express your analysis quickly and visually. </span>

<span data-preserver-spaces="true">Here's an example dashboard you can create with Dash:</span>

<img class="size-full wp-image-12273" src="" alt="Image 1 - Ternary Map Explorer Dash dashboard" width="2900" height="2094" /> Image 1 - Ternary Map Explorer Dash dashboard
<blockquote><strong>Want to see more dashboard examples? <a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer">Check out Plotly's official app gallery</a>.</strong></blockquote>
<span data-preserver-spaces="true">On the other hand, R Shiny is an open-source package for building web applications with R. It provides a robust web framework for developing any sort of app, not only dashboards. </span><span data-preserver-spaces="true">Shiny is easy and intuitive to use, as you'll see in the examples below. It also doesn't require any HTML, CSS, or JavaScript knowledge - but this is helpful if you want extra customizability.</span>

<span data-preserver-spaces="true">Here's an example dashboard you can create with Shiny:</span>

<img class="size-full wp-image-12263" src="" alt="Image 2 - Shiny Enterprise Dashboard" width="2900" height="2094" /> Image 2 - Shiny Enterprise Dashboard

<strong><span data-preserver-spaces="true">Winner: Tie.</span></strong><span data-preserver-spaces="true"> You can develop identical solutions with both Dash and Shiny.</span>
<h2 id="boilerplate"><span data-preserver-spaces="true">Dash vs. Shiny: Which Requires More Boilerplate Code?</span></h2>
<span data-preserver-spaces="true">Every web framework comes with a chunk of code needed for the application to run, named <strong>boilerplate</strong>. </span><span data-preserver-spaces="true">This section will show you how much code is needed to start Dash and Shiny application. You will create two identical applications by the end, each showing only a single H3 element. Let's begin with Dash.</span>

<iframe width="100%" frameborder="0" id="gist-darioappsilon/292556c43a3986592abc36138b9411aa" data-lf-form-tracking-inspected-3p1w24dwwdp7my5n="true" data-lf-yt-playback-inspected-3p1w24dwwdp7my5n="true" data-lf-vimeo-playback-inspected-3p1w24dwwdp7my5n="true" style="height: 301px;"></iframe>

import dashimport dash_html_components as html
app = dash.Dash(name) app.layout = html.Div(children=[    html.H3('Dash App')])
if name == 'main':    app.run_server(debug=True)</code></pre>

<iframe><script> src=""></script></iframe>

<span data-preserver-spaces="true">Here's the corresponding application:</span>

<img class="size-full wp-image-12249" src="" alt="Image 3 - Basic Dash application" width="2900" height="2094" /> Image 3 - Basic Dash application

<span data-preserver-spaces="true">So eleven lines in total, and we haven't imported any data visualization library. Three lines are empty, which are used for formatting purposes. In general - </span>not bad<span data-preserver-spaces="true">. Let's see what's the deal with Shiny:</span>

<script src=""></script>

<span data-preserver-spaces="true">Only nine lines here, of which three are empty. Here's the corresponding application:</span>

<img class="size-full wp-image-12251" src="" alt="Image 4 - Basic Shiny application" width="2900" height="2094" /> Image 4 - Basic Shiny application

<strong><span data-preserver-spaces="true">Winner: R Shiny.</span></strong><span data-preserver-spaces="true"> Does it really matter much, though? It's only boilerplate code, after all. At this initial stage – no, it seems like it doesn't matter. However, for more advanced applications, Dash requires a lot more boilerplate code than Shiny. For instance, there are no reactive intermediate variables with Dash, which is a big drawback. We'll return to this theme of Shiny ease-of-use throughout the article.</span>
<h2 id="boilerplate"><span data-preserver-spaces="true">How to Create UI Elements in Dash vs. Shiny</span></h2>
<span data-preserver-spaces="true">Let's continue our comparison by taking a look at UI elements. The goal is to create the same form-based application in both Dash and Shiny. The application should be used to filter job candidates by level, skills, and experience. It also allows you to specify additional points of interest.</span>

<span data-preserver-spaces="true">Let's start with Python's Dash. All of the core UI components are available in the <code>dash_core_componenets</code> library. The convention is to import it abbreviated as <code>dcc</code>. Other imports and boilerplate remain the same. </span>

<span data-preserver-spaces="true">Here's the code for a simple form-based application:</span>

<script src=""></script>

<span data-preserver-spaces="true">And here's the corresponding application:</span>

<img class="size-full wp-image-12265" src="" alt="Image 5 - Simple form-based application in Python Dash" width="2900" height="2094" /> Image 5 - Simple form-based application in Python Dash

<span data-preserver-spaces="true">Dash doesn't include too many styles by default, so you'll have to do it independently It can be considered both as a pro (advanced CSS users will have to reset the styles anyway) and as a con (if you want to stick with default stylings). </span>

<span data-preserver-spaces="true">Let's replicate the same application with R and Shiny:</span>

<script src=""></script>

<span data-preserver-spaces="true">Here's the corresponding application:</span>

<img class="size-full wp-image-12267" src="" alt="Image 6 - Simple form-based application in R Shiny" width="2900" height="2094" /> Image 6 - Simple form-based application in R Shiny

<span data-preserver-spaces="true">As you can see, Shiny includes a ton more styling straight out of the box. Shiny applications look better than Dash applications by default. However, who wants their apps to look "default" anyway? We'll cover custom styling in the next section.</span>

<strong><span data-preserver-spaces="true">Winner: R Shiny.</span></strong><span data-preserver-spaces="true"> You can create a better-looking application with less code.</span>
<h2 id="styling-ui-1"><span data-preserver-spaces="true">How to Style UI with CSS in Dash vs. Shiny</span></h2>
<span data-preserver-spaces="true">Nobody likes a generic-looking application. The aesthetics of your app are tied directly with how users feel about it. With advancements in design, we're used to commercial apps looking spectacular. That doesn't mean developing great-looking apps is easy, especially for developers.</span>

<span data-preserver-spaces="true">Still, adding a touch of <a href="" target="_blank" rel="noopener noreferrer">style through CSS</a> is more or less a must for your app. This section compares how easy it is to add styles to both Dash and Shiny if the same stylesheets look identical across the two. Who knows, maybe default stylings on Shiny will come as a drawback. </span><span data-preserver-spaces="true">Later, we'll compare how easy it is to add custom CSS frameworks like Boostrap to your app.</span>

<span data-preserver-spaces="true">A CSS file for the Dash application goes to the <code>assets</code> folder and in the <code>www</code> folder for Shiny apps. Create these folders in a root directory, where your application file is. </span>

<span data-preserver-spaces="true">Here's the complete CSS for both Dash and Shiny - called <code>main.css</code>:</span>

<script src=""></script>

<span data-preserver-spaces="true">Let's now use it to create a simple styled application - first with Dash:</span>

<script src=""></script>

<span data-preserver-spaces="true">Here's the corresponding application:</span>

<img class="size-full wp-image-12269" src="" alt="Image 7 - Styled Dash application" width="2900" height="2094" /> Image 7 - Styled Dash application

<span data-preserver-spaces="true">The stylings work just as for any regular web application. That's because Dash didn't add its default styles as Shiny did.</span>

<span data-preserver-spaces="true">Here's the code for a styled R Shiny app:</span>

<script src=""></script>

<span data-preserver-spaces="true">And here's the corresponding dashboard:</span>

<img class="size-full wp-image-12271" src="" alt="Image 8 - Styled Shiny application" width="2900" height="2094" /> Image 8 - Styled Shiny application

<span data-preserver-spaces="true">Well, that obviously doesn't look right. The more elaborate default Shiny styling is conflicting with our custom styling. Shiny needs a bit more work with stylings than Dash, but that's something you can quickly get used to. Still, the included styling with default Shiny apps means that there is a bit more work required to add custom styling to a Shiny app than a Dash app at a basic level.</span>

<strong><span data-preserver-spaces="true">Winner: Dash</span></strong><span data-preserver-spaces="true">. This doesn't mean you can't make <a href="">Shiny apps look fantastic</a>, though.</span>
<h2 id="styling-ui-2"><span data-preserver-spaces="true">How to Style UI with Bootstrap in Dash vs. Shiny</span></h2>
Let's discuss CSS frameworks. Bootstrap's been one of the most popular frameworks for years, so naturally, you might want to include it in your apps. It's a great way to introduce new design elements and <a href="">give your apps a fresher look</a>. Your apps will still look kind of "default" - that's mostly because Bootstrap has been out for so long and we've come to associate it with a "standard" appearance. Anyone who has been in web design/development for more than three days knows how Bootstrap components look like.

Including Bootstrap in Dash is easy. You have to install the <code>dash_bootstrap_components</code> library and you're good to go. The code below shows you how to create a navigation bar and a jumbotron in Dash:

<script src=""></script>

Here's the corresponding application:

<img class="size-full wp-image-12253" src="" alt="Image 9 - Dash and Bootstrap" width="2900" height="2094" /> Image 9 - Dash and Bootstrap

R Shiny is different. It comes with Bootstrap out of the box, but not with the most recent version. Bootstrap version 4.5 is the latest at this point, but Shiny is still stuck on 3.3.5. One solution for addressing this issue is by using the <code>bslib</code> library:

<script src=""></script>

<img class="size-full wp-image-12261" src="" alt="Image 10 - Shiny and Bootstrap" width="2900" height="2094" /> Image 10 - Shiny and Bootstrap

<span data-preserver-spaces="true">As you can see, it is a code-heavy solution. It requires you to specify every CSS class and other properties as if you were writing in pure HTML. Declaring a winner in this department is a no-brainer.</span>

<strong><span data-preserver-spaces="true">Winner: Dash</span></strong><span data-preserver-spaces="true"><strong>.</strong> Using Bootstrap is much cleaner in Dash than in Shiny.</span>
<h2 id="reactivity">Reactivity in Dash vs. Shiny</h2>
<span data-preserver-spaces="true">Dashboards shouldn't look and behave like plain reports. They have to be interactive. Users won't like your dashboards if they can't easily change what's displayed and even interact with individual data points. That's where reactivity (or callbacks) comes in. </span><span data-preserver-spaces="true">Options are endless - you can update every component as a single input change, update only selected components, delay updates until the button is pressed, etc. We'll stick to the basics and perform the update when any of the inputs change.</span>

<span data-preserver-spaces="true">For this example, we'll have a single text input and two dropdown menus. Their values determine what the visualization looks like. The text input is used to change the title, and the two dropdowns are used for attributes shown on the X and Y axes.</span>

<span data-preserver-spaces="true">Let's start with Python and Dash. Here's the code:</span>

<script src=""></script>

<span data-preserver-spaces="true">And here's the corresponding dashboard:</span>

<img class="size-full wp-image-12257" src="" alt="Image 11 - Reactivity demonstration with Python Dash" width="1334" height="922" /> Image 11 - Reactivity demonstration with Python Dash

<span data-preserver-spaces="true">It's a simple dashboard but requires a fair amount of code. Nevertheless, the code is simple to read and understand. Dash uses <code>@app.callback</code> decorator pattern to handle reactivity. You can update as many components in a single callback and get values from as many components as needed.</span>

<span data-preserver-spaces="true">R Shiny is a bit simpler. It needs significantly less code to produce the same output. Still, the syntax might look strange if you're not used to R (e.g., double exclamation point in front of column names). </span>

<span data-preserver-spaces="true">Here's the code for producing the identical dashboard:</span>

<script src=""></script>

<span data-preserver-spaces="true">Here's the corresponding dashboard:</span>

<img class="size-full wp-image-12259" src="" alt="Image 12 - Reactivity demonstration with R Shiny" width="1334" height="922" /> Image 12 - Reactivity demonstration with R Shiny

<strong><span data-preserver-spaces="true">Winner: R Shiny</span></strong><span data-preserver-spaces="true"><strong>.</strong> Shiny requires less code than Dash for better-looking output.</span>
<h2 id="publishing">Publishing and Deployment in Dash vs. Shiny</h2>
Dashboard development is fun, but what about deployment? Most businesses don't tend to leave dashboards sitting idle on a developer's PC. Whether you're working for yourself or for a client, publishing/deployment is a necessary step. As it turns out, you're not limited to either library.

When it comes to R Shiny, deployment possibilities are next to endless. You can host your app as a <strong>GitHub gist</strong> (single file only), use a service such as <a href="" target="_blank" rel="noopener noreferrer"><strong></strong></a>, do everything manually by hosting a <a href="" target="_blank" rel="noopener noreferrer"><strong>Shiny Server</strong></a>, create a <strong>Docker container</strong> around the dashboard, and everything in between.
<blockquote>Want to learn more about sharing Shiny apps? <a href="" target="_blank" rel="noopener noreferrer">Here are three free options - from simple to AWS</a>.</blockquote>
The same holds true for Python and Dash. Sure, you can't use online services specific to R Shiny, but we don't see that as an issue. It's likely you want full control over the deployment process, especially if you're working on a dashboard for a client. You can't go wrong by <strong>Dockerizing</strong> your Dash application and deploying it to the cloud (e.g., on Amazon AWS EC2 instance). With Dash, you also have the option to use <strong><a href="" target="_blank" rel="noopener noreferrer">Dash Enterprise</a></strong> for deployment, which isn't free.

There are enterprise options for R Shiny too, but you get the gist - deployment isn't a deciding factor.

<strong>Winner: Tie.</strong> You can deploy both Shiny and Dash apps pretty much everywhere.
<h2 id="anchor-7"><span data-preserver-spaces="true">Python Dash vs. R Shiny: Final Face-off</span></h2>
<span data-preserver-spaces="true">The final results are in:</span>
<ul><li><span data-preserver-spaces="true">R Shiny - 3 points</span></li><li><span data-preserver-spaces="true">Python Dash - 2 points</span></li><li><span data-preserver-spaces="true">Tie - 2 points</span></li></ul>
<span data-preserver-spaces="true">It looks like R Shiny is ahead by a single point. Does this mean that R Shiny is better for everyone and every scenario? <strong>Absolutely n</strong></span><strong><span data-preserver-spaces="true">ot</span></strong><span data-preserver-spaces="true">. You can develop identical production-ready applications in both technologies. What you choose depends on your specific needs and preferences.</span>

<span data-preserver-spaces="true">R Shiny is a bit faster for developers. It requires less code than Dash for identical solutions. That's if you decide to not use Bootstrap in your dashboards. Further, creating custom components in Dash requires extensive React.js knowledge, which is a large hurdle. Dash also falls short with intermediate reactive variables. Using them requires you to create a hidden div to store and reuse calculations. An <a href="" target="_blank" rel="noopener noreferrer">alternative solution</a> exists, but it's still a big drawback when compared to R Shiny.</span>
<blockquote>What else can you do with Shiny? Check out our free <a href="">Shiny dashboard templates</a>.</blockquote>
<span data-preserver-spaces="true">If you need to create powerful, customizable, and interactive dashboards that look great and respond to user input, Shiny is a clear choice. It requires a bit of coding knowledge even for simple dashboards, but R isn't a very complicated language. You can quickly get up to speed in a couple of weeks </span><a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">or even a couple of days</span></a><span data-preserver-spaces="true">, depending on your prior knowledge of programming. </span><strong><span data-preserver-spaces="true">If you want to make a scalable enterprise Shiny dashboard, then you can always reach out to </span></strong><a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer"><strong><span data-preserver-spaces="true">Appsilon </span></strong></a><strong><span data-preserver-spaces="true">for help. </span></strong><span data-preserver-spaces="true">We're continuously pushing the limits of what's possible with Shiny, and we'd be happy to guide you and your company.</span>
<h3><span data-preserver-spaces="true">Learn More</span></h3><ul><li><a href="" target="_blank" rel="noopener">Introduction to Data Science in Python</a></li><li><a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Tableau vs. R Shiny: Which Excel Alternative Is Right For You?</span></a></li><li><a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">PowerBI vs. R Shiny: Two Popular Excel Alternatives Compared</span></a></li><li><a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">How to Switch from Excel to R Shiny: First Steps</span></a></li><li><span data-preserver-spaces="true"><a class="editor-rtfLink" href="" target="_blank" rel="noopener noreferrer">Make R Shiny Dashboards Faster with updateInput, CSS, and JavaScript</a></span></li></ul>

Contact us!
Damian's Avatar
Damian Rodziewicz
Head of Sales
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
shiny dashboards