R

R

898 bookmarks
Newest
Making Tables Shiny: DT, formattable, and reactable
Making Tables Shiny: DT, formattable, and reactable
Demo of popular packages for generating interactive tables suitable for Shiny apps
formattable Another nice table-making package is formattable. The cute heatmap-style colour formatting and the easy-to-use formatter functions make formattable very appealing. color_tile() fills the cells with a colour gradient corresponding to the values color_bar() adds a colour bar to each cell, where the length is proportional to the value The true_false_formatter() defined below demonstrates how to define your own formatting function, in this case formatting TRUE, FALSE and NA as green, red and black.
If you want the features of both DT and formattable, you can combine them by converting the formattable() output to as.datatable(), and much of the formattable features will be preserved.
However, one problem I had was that when using DT::datatable, missing values (NA) are left blank in the display (which I prefer), but in the converted from formattable() version, NA’s are printed. Also, color_bar columns seem to be converted to character, which can no longer be sorted numerically.
reactable Next I tried reactable, a package based on the React Table library.
Columns are customised via the columns argument, which takes a named list of column definitions defined using colDef(). These include format definitions created using colFormat.
In the end, I used DT::datatable() in my Shiny app, because I found it the easiest, fastest, and most comprehensive. I’ve been able to achieve most of the features I wanted using just DT.
Heatmap-like fill effect:
apply the formatStyle() function to the output of datatable() to set the backgroundColor for selected columns:
Abbreviate long cells
Sometimes some cells have a large amount of text that would mess up the table layout if I showed it all. In these cases, I like to abbreviate long values and show the full text in a tooltip. To do this, you can use JavaScript to format the column to show a substring with “…” and the full string in a tooltip (<span title="Long string">Substring...</span) when values are longer than N characters (in this case 10 characters). You can do this using columnDefs and pass JavaScript with the JS() function:
Really plain table Sometimes I don’t need any of the faff. Here’s how to get rid of it all:
headerCallbackRemoveHeaderFooter <- c( "function(thead, data, start, end, display){", " $('th', thead).css('display', 'none');", "}" )
datatable( my_pic_villagers, options = list( dom = "t", ordering = FALSE, paging = FALSE, searching = FALSE, headerCallback = JS(headerCallbackRemoveHeaderFooter) ), selection = 'none', callback = JS( "$('table.dataTable.no-footer').css('border-bottom', 'none');" ), class = 'row-border', escape = FALSE, rownames = FALSE, filter = "none", width = 500 )
·clarewest.github.io·
Making Tables Shiny: DT, formattable, and reactable
rstudio/shiny: Easy interactive web applications with R
rstudio/shiny: Easy interactive web applications with R
Easy interactive web applications with R.
Compared to event-based programming, reactivity allows Shiny to do the minimum amount of work when input(s) change, and allows humans to more easily reason about complex MVC logic.
An attractive default look based on Bootstrap which can also be easily customized with the bslib package or avoided entirely with more direct R bindings to HTML/CSS/JavaScript.
Tools for improving and monitoring performance, including native support for async programming, caching, load testing, and more.
·github.com·
rstudio/shiny: Easy interactive web applications with R
Shiny - Stop-Trigger-Delay
Shiny - Stop-Trigger-Delay
Shiny is a package that makes it easy to create interactive web apps using R and Python.
observeEvent() is used to perform an action in response to an event eventReactive() is used to create a calculated value that only updates in response to an event
observe() and reactive() functions automatically trigger on whatever they access observeEvent() and eventReactive() functions need to be explicitly told what triggers them
And where does isolate fit in all this? isolate() is used to stop a reaction observeEvent() is used to perform an action in response to an event eventReactive() is used to create a calculated value that only updates in response to an event
·shiny.posit.co·
Shiny - Stop-Trigger-Delay
UNCHARTED DATA: Automating Workflows with GitHub Actions
UNCHARTED DATA: Automating Workflows with GitHub Actions
How to automate data collection and app deployment with GitHub Actions.
Create .Renviron file Within the get_data.R script of my repository, I extract my EIA API key from my R environment so that I can connect to the EIA API and pull the data needed for my project. In order for this to occur during my workflow, I need to create an .Renviron file within my virtual environment and store the key within that environment. - name: Create and populate .Renviron file run: | echo EIA_API_KEY="$EIA_API_KEY" >> ~/.Renviron shell: bash
·uncharteddata.netlify.app·
UNCHARTED DATA: Automating Workflows with GitHub Actions
UNCHARTED DATA: Using Crosstalk to Add User-Interactivity
UNCHARTED DATA: Using Crosstalk to Add User-Interactivity
Linking an interactive plot and table together with the crosstalk package.
Using Crosstalk to Add User-Interactivity
The goal is to link the reactable table I created to a plotly chart and provide additional filter options that control both the table and the chart.
An important note: in order to use crosstalk, you must create a shared dataset and call that dataset within both plotly and reactable. Otherwise, your dataset will not communicate and filter with eachother. The code to do this is SharedData$new(dataset).
If you expand the code below, you’ll see that the code to build a table in reactable is quite extensive. I will not go into the details in this post, but do recommend a couple great tutorials that I used to create the interactive table such as this tutorial from Greg Lin, and this from Tom Mock which really helped me understand how to use CSS and Google fonts to enhance the visual appeal of the table (see the “Additional CSS Used for Table” section below for more info).
If you have ever built something in Shiny before, you’ll notice that the crosstalk filters are very similar. You can add a filter to any existing column in the dataset. As you can see in the code below, I used a mixture of filter_checkbox and filter_select depending on how many unique options were available in the column you’re filtering. My rule of thumb is if there are more than five options to choose from it’s probably better to put them into a list in filter_select like I did with the Division filtering as to not take up too much space on the page.
For the layout of the data visualization, I used bscols to place the crosstalk filters side-by-side with the interactive plotly chart. I then placed the reactable table underneath and added a legend to the table using tags from the htmltools package. The final result is shown below. Feel free to click around and the filters and you will notice that both the plot and the table will filter accordingly. Another option is to drag and click on the plot and you will see the table underneath mimic the teams shown.
·uncharteddata.netlify.app·
UNCHARTED DATA: Using Crosstalk to Add User-Interactivity
Design Patterns in R
Design Patterns in R
Build robust and maintainable software with object-oriented design patterns in R. Design patterns abstract and present in neat, well-defined components and interfaces the experience of many software designers and architects over many years of solving similar problems. These are solutions that have withstood the test of time with respect to re-usability, flexibility, and maintainability. R6P provides abstract base classes with examples for a few known design patterns. The patterns were selected by their applicability to analytic projects in R. Using these patterns in R projects have proven effective in dealing with the complexity that data-driven applications possess.
·tidylab.github.io·
Design Patterns in R
The most efficient way to manage snapshot tests in R.
The most efficient way to manage snapshot tests in R.
Use CI and Github API
Snapshot testing gets difficult when there is more than one variant of the same result. The reason why snapshot testing might be discouraging is due to the fact that snapshots will most likely fail due to environment settings. If one person runs the tests on a Mac and another on a Linux machine, the snapshots of rendered images will almost certainly be different. Comparing these snapshots will result in a failed test even though the code is correct. Add CI to the mix, and you have a hot mess.
The easiest solution is to introduce variants. Variants are versions of snapshots which were created on different environments. In {testthat} variants are stored in separate directories. You can pass a name of the variant to the variant argument of testthat::test_snapshot. If you have a Linux, set variant = "linux", if you have a Mac, set variant = "mac".
Use snapshots generated on CI as the source of truth. Don’t check in snapshots generated on your machine. Generate them on CI and download them to your machine instead.
Step 1: Archive snapshots on CI Add this step to you CI testing workflow to allow downloading generated snapshots.
- name: Archive test snapshots if: always() uses: actions/upload-artifact@v3 with: name: test-snapshots path: | tests/testthat/_snaps/**/**/*
Step 2: Detect the environment to create variants We can create a make_variant function to detect the version of the platform, as well as if we are running on CI. This way even if we use the same OS on CI and locally, we can still differentiate between snapshots generated on CI and locally.
#' tests/testthat/setup.R is_ci <- function() { isTRUE(as.logical(Sys.getenv("CI"))) } make_variant <- function(platform = shinytest2::platform_variant()) { ci <- if (is_ci()) "ci" else NULL paste(c(ci, platform), collapse = "-") } # In tests: testthat::expect_snapshot(..., variant = make_variant())
Step 3: Ignore your local snapshots Don’t check in snapshots generated on your machine. Add them to .gitignore instead. Copy tests/testthat/_snaps/linux-4.4 This way we can still generate snapshots locally to get fast feedback, but we’ll only keep a single source of truth checked in the repository. Since you don’t track changes in local snapshots, you need to regenerate them before you start making changes to see if they change. It adds some complexity to the process, but it allows to keep the number of shared snapshots in the version control minimal. Alternatively, you can keep local snapshots, but when doing code review, focus only on the ones generated on CI.
Step 4: Automate downloading snapshots from CI To update snapshots generated on CI in Github, we need to: Go to Actions. Find our workflow run. Download the test-snapshots artifact. Unpack and overwrite the local snapshots. testthat::snapshot_review() to review the changes. Commit and push the changes. This is a lot of steps. We can automate the most laborious ones with Github API.
The .download_ci_snaps function will: Get the list of artifacts in the repository identified by repo and owner. It’ll search workflows generated from the branch we’re currently on. It will download the latest artifact with the provided name (in our case its “test-snapshots”) in the repository Unzip them and overwrite the local copy of snapshots.
·jakubsob.github.io·
The most efficient way to manage snapshot tests in R.
Fast JSON, NDJSON and GeoJSON Parser and Generator
Fast JSON, NDJSON and GeoJSON Parser and Generator
A fast JSON parser, generator and validator which converts JSON, NDJSON (Newline Delimited JSON) and GeoJSON (Geographic JSON) data to/from R objects. The standard R data types are supported (e.g. logical, numeric, integer) with configurable handling of NULL and NA values. Data frames, atomic vectors and lists are all supported as data containers translated to/from JSON. GeoJSON data is read in as simple features objects. This implementation wraps the yyjson C library which is available from .
·coolbutuseless.github.io·
Fast JSON, NDJSON and GeoJSON Parser and Generator
Literate Programming for Writing R Packages
Literate Programming for Writing R Packages
Allows one to fully create an R package in a single .Rmd file. Includes functionality and .Rmd templates for a literate programming approach to R package development.
·jacobbien.github.io·
Literate Programming for Writing R Packages