DEV Community

Romi Mendez
Romi Mendez

Posted on

Transform your R Dataframes: Styles, 🎨 Colors, and 😎 Emojis

A few weeks ago I wrote an article about pandas dataframes and how to assign styles, but I received messages about how to do it in R (my first loveπŸ₯° in languages with data) and so I decided to rewrite the article using R libraries.

So in the next section of this article, we will explore a method to add 🎨colors and πŸ–ŒοΈstyles in R DataFrames. We will focus on the application of colors and emojis, using approaches similar to the popular conditional formatting commonly used in pivot tables within spreadsheets. Through this strategy, we aim to improve the presentation of our data, making the exploration and understanding of the information not only informative but also visually attractive.


What libraries can I use to style my R dataframes?

The R libraries used to create this article are as follows:

Image description

  1. πŸ” tidyverse: Among the best, it integrates various R libraries for data manipulation, graphics, and analysis, promoting clear and efficient code.

  2. πŸ“ knitr: Automates the generation of dynamic reports.

  3. πŸ“ kableExtra: An additional extension that enhances table presentation in R Markdown documents with extra formatting options.

  4. πŸ“„ reactablefrmtr: Incorporates functions to craft interactive and flexible tables in R, featuring filtering, sorting, and search functionalities.

  5. ✏️ htmltools: Offers functions to build and manipulate HTML objects in R.

  6. πŸ“„ formattable: Equipped with functions for formatting and customizing tables in R.

  7. πŸ“„ flextable: Another library enabling the creation of flexible and customizable tables in R, with advanced formatting options for documents and presentations.

  8. πŸ“Š ggplot2: Among the most popular R visualization libraries, it produces appealing and comprehensible graphs.

  9. 🎨 viridis: A R library for creating visually appealing color maps


These libraries empowered me to employ functions for generating HTML-style representations of DataFrames. This capability enables customization of DataFrame visual appearance during viewing.

The functions employed in this article facilitate the highlighting, coloring, and formatting of cells based on specific conditions. This makes it effortless to visually identify patterns and trends within datasets.

Image description


🟣 Pivot Tables

The pivot table is a tabular data structure that provides a summarized overview of information from another table, organizing the data based on one variable and displaying values associated with another variable. In this specific scenario, the pivot table organizes the data according to the β€˜smoker’ column and presents the total sum of tips, categorized by the days on which clients consume in the restaurant

Image description

Example

The following example shows the pivot_table method with the β€˜tips’ DataFrame

r code

library(reshape2)
library(tidyverse)

data = tips
data_pivot <- data %>%
  group_by(smoker, day) %>%
  summarise(total_bill = sum(total_bill), .groups = 'drop') %>%
  pivot_wider(names_from = day, values_from = total_bill)

data_pivot

Enter fullscreen mode Exit fullscreen mode

ouput

day smoker Thur Fri Sat Sun
0 Yes 326.24 252.20 893.62 458.28
1 No 770.09 73.68 884.78 1168.88

🟣 Dataframe: Apple Store apps

In this analysis, we will use the β€˜πŸŽ Apple Store apps’ DataFrame to explore the creation of pivot tables and customization of table styles. This dataset provides detailed insights into Apple App Store applications, covering aspects from app names to specifics like size, price, and ratings. Our objective is to efficiently break down the information while applying styles that enhance the presentation and comprehension of data effectively.

The dataset was downloaded from Kaggle and it contains more than 7000 Apple iOS mobile application details. It is important to note that the data was collected in July 2017.

Data Schema overview

column_name Β column description
track_name the column contains the name of the app.
size_bytes the column contains the size of the app in bytes.
currency the column contains the currency type.
price the column contains the price of the app.
rating_count_tot the column contains the total number of ratings.
rating_count_ver the column contains the number of ratings for the current version of the app.
user_rating the column contains the average user rating for the app.
user_rating_ver the column contains the average user rating for the current version of the app.
ver the column contains the current version of the app.
cont_rating the column contains the content rating.
prime_genre the column contains the primary genre.
sup_devices.num the column contains the number of supported devices.
ipadSc_urls.num the column contains the number of screenshots showed for display.
lang.num the column contains the number of supported languages.
vpp_lic the column contains the Vpp Device Based Licensing Enabled.

🟣 Create Dataframe

In the following code chunk, we will create a DataFrame by reading the CSV file.

print("Libraries version:")
print(strrep('---', 10))
print(paste0("tidyverse: ",packageVersion("tidyverse")[1]))
Enter fullscreen mode Exit fullscreen mode
[1] "tidyverse version: 1.3.1"
Enter fullscreen mode Exit fullscreen mode
# Create a dataframe from a csv file
# You can download the file from the following link https://github.com/r0mymendez/pandas-styles
path = 'https://raw.githubusercontent.com/r0mymendez/pandas-styles/main/data/AppleStore.csv'
data = read_delim(path , delim = ";")
Enter fullscreen mode Exit fullscreen mode

🟣 Pivot Table

In the next step, our goal is to generate a dynamic table from a Dataframe, in which the top 15 genres with the largest number of applications are filtered.

r code

# Pivot table

# filter the data to keep only the top 15 genres
top_genre = data %>%
  group_by(prime_genre) %>%
  summarise(count = n(), .groups = 'drop') %>%
  arrange(desc(count)) %>%
  head(n = 15) %>%
  pull(prime_genre)


tmp = data %>%
  filter(prime_genre %in% top_genre) %>%
  select(prime_genre, user_rating, price)


# create a new column with the rating rounded to the nearest integer
tmp$user_rating = paste0("rating_", as.character(trunc(tmp$user_rating)))


# create a pivot table
tmp_pivot <- tmp %>%
  group_by(prime_genre, user_rating) %>%
  summarise(price = mean(price, na.rm = TRUE), .groups = 'drop') %>%
  pivot_wider(names_from = user_rating, values_from = price, values_fill = 0) %>%
  mutate(across(where(is.numeric), ~round(., 2)))


# print the pivot table
tmp_pivot
Enter fullscreen mode Exit fullscreen mode

Image description


 🟣 Styles with R libraries

Now we will explore the functions of the aforementioned libraries that will allow us to improve the visual presentation of DataFrames. This functionality provides us with different options to modify the appearance of the data, allowing us to customize aspects such as:

  • Highlighting: Emphasize specific rows, columns, or values.

  • Formatting: Adjust the format of the displayed values, including precision and alignment.

  • Bar Charts: Represent data with horizontal or vertical bar charts within cells.


 🎨 Styling: Setting Background Color for Headers

In this section, we will apply styles to both the titles and the table. Therefore we use background colors to highlight the headers and the rest of the table.

r code

library(knitr)
library(kableExtra)

kable(tmp_pivot, "html") %>%
  kable_styling("striped", full_width = F) %>%
  row_spec(0, background = "#5E17EB", color = "white")
Enter fullscreen mode Exit fullscreen mode

Image description


🎨 Style: Setting the background color for a particular cell

In following code snippet illustrates how to set a custom background color for a particular cell in our DataFrame using pandas styling.

value = 4

tmp_pivot %>%
  mutate(
    rating_4 = cell_spec(rating_4, "html", 
                    background = if_else(tmp_pivot$rating_4>value, "#FD636B", "#ECE3FF"),
                    color = if_else(tmp_pivot$rating_4>value, "white", "black")
    )
  ) %>%
  kable(format = "html", escape = F) %>%
  kable_styling("striped", full_width = FALSE) %>%
  row_spec(0, background = "#5E17EB", color = "white") %>%
  column_spec(1:ncol(tmp_pivot), background = "#ECE3FF", color = "black")
Enter fullscreen mode Exit fullscreen mode

Image description


🎨 Style: Setting the background color for max/min values in the dataframe

Now, we will focus on highlighting the maximum and minimum values in our DataFrame. For this reason, we will assign distinctive background colors to these extreme values, facilitating a quicker and more intuitive understanding of the dataset. The code snippet below demonstrates how to implement this stylistic enhancement.

rating_columns <- grep("^rating", names(tmp_pivot), value = TRUE)
max_value <- max(unlist(tmp_pivot %>% select(rating_columns), use.names = FALSE))
min_value <- min(unlist(tmp_pivot %>% select(rating_columns), use.names = FALSE))

# The next function to apply specific formatting and preserve the original
format_spec <- function(x) {
  if_else(x == max_value, sprintf("%.2f", x),
          if_else(x == min_value, sprintf("%.2f", x),
                  sprintf("%.2f", x)))
}

tmp_pivot %>%
  mutate(
    across(rating_columns, 
           ~ cell_spec(format_spec(.x),
          "html", 
           background = if_else(. == max_value, "#3BE8B0",
                                if_else(. == min_value, "#FF66C4", "#ECE3FF")),
           bold = if_else(. == max_value, TRUE,if_else(. == min_value, TRUE, FALSE))
                )
         )
  ) %>%
  kable(format = "html", escape = F) %>%
  kable_styling("striped", full_width = FALSE) %>%
  row_spec(0, background = "#5E17EB", color = "white") %>%
  column_spec(1:ncol(tmp_pivot), background = "#ECE3FF", color = "black")
Enter fullscreen mode Exit fullscreen mode

Image description


🎨 Style: Color Background Gradients

In the upcoming section, we will delve into the concept of color maps, representing a spectrum of colors arranged in a gradient.
A colormap, essentially a palette of colors, consists of distinctive denominations, with the most popular ones being ['viridis,' 'magma,' 'inferno,' 'plasma', 'cividis'].

The primary objective behind creating these color spectrums is to enhance the visual representation of data.
Each color in the gradient carries specific nuances, contributing to a more nuanced data visualization experience.

library(viridisLite)  
library(viridis)
library(unikn)  # load package
seecol(pal = pal_unikn)

# Reference of the following code: https://bookdown.org/hneth/ds4psy/D-4-apx-colors-pkgs.html
n <- 10  # number of colors

# define 5 different color scales (n colors each):
v1 <- viridis(n)
v2 <- magma(n)
v3 <- inferno(n)
v4 <- plasma(n)
v5 <- cividis(n)

# See and compare color scales:
seecol(list(v1, v2, v3, v4, v5), 
       col_brd = "white", lwd_brd = 4, 
       title = "Various viridis color palettes (n = 10)",
       pal_names = c("v1: viridis", "v2: magma", "v3: inferno", "v4: plasma",  "v5: cividis"))
Enter fullscreen mode Exit fullscreen mode

Image description


🎨 Viridis palette

Now, we will apply a color gradient to our pivot table, allowing you to observe how it is colored using the Viridis palette. In this context, lighter colors signify larger values within the distribution, while darker shades correspond to smaller values in the distribution. This approach provides a visual representation that intuitively conveys the magnitude of the data, making it easier to discern patterns and variations across the dataset.

# Calculate maximum and minimum values
max_value <- max(unlist(tmp_pivot %>% select(rating_columns), use.names = FALSE))
min_value <- min(unlist(tmp_pivot %>% select(rating_columns), use.names = FALSE))

# Define the number of cuts for the "viridis" palette
num_cuts <-nrow(tmp_pivot)

xc <- seq(min_value, max_value, length.out = num_cuts)
pal <- viridis(num_cuts)

# Apply color gradients to each cell with viridis 
styled_table <- map(tmp_pivot, function(col) {
  if (is.numeric(col)) {
    cell_spec( format_spec(col),
               "html", 
               background = pal[cut(col, breaks = xc, include.lowest = TRUE)])
  } else {
    cell_spec(col, "html")
  }
}) %>%
  as.data.frame() %>%
  kable(format = "html", escape = F)  %>%
  kable_styling("striped", full_width = FALSE)  %>%
  row_spec(0, background = "#440154FF", color = "white") %>%
  column_spec(2:ncol(tmp_pivot), color = "white") %>%
  column_spec(1:1, background = "#ECE3FF") 

styled_table
Enter fullscreen mode Exit fullscreen mode

Image description


🎨 Style: Color Background by columns

In the next code chunk, we will enhance the visual representation of our pivot table by introducing distinct color backgrounds to specific columns. This technique aids in better highlighting and categorizing data, making it easier to draw insights from the table.

tmp_pivot%>%
  kable(format = "html", escape = F)  %>%
  kable_styling("striped", full_width = FALSE)  %>%
  column_spec(2:3, background = "#FFCFC9", color = "black") %>%
  column_spec(4:5, background = "#FFF1B0", color = "black") %>%
  column_spec(6:7, background = "#BEEAE5", color = "black")%>%
  row_spec(0, background = "#440154FF", color = "white") %>%
  column_spec(1:1, background = "#ECE3FF") 
Enter fullscreen mode Exit fullscreen mode

Image description


🎨 Style: Color Bar

In this section, we will implement the color_bar function to introduce a dynamic color bar into our DataFrame. The color bar provides a visual representation of data values, assigning varying colors to different data ranges.

library(htmlwidgets)
library(htmltools)
library(formattable)

formattable(tmp_pivot, list(
  prime_genre = formatter("span", style = ~ style(background = "#ECE3FF", font.weight = "bold")),
  rating_0 = color_bar("#FFCFC9"),
  rating_1 = color_bar("#FFCFC9"),
  rating_2 = color_bar("#FFF1B0"),
  rating_3 = color_bar("#FFF1B0"),
  rating_4 = color_bar("#BEEAE5"),
  rating_5 = color_bar("#BEEAE5")
)) %>%
  as.htmlwidget() %>%
  prependContent(tags$style("th { padding: 0px !important; background: #5E17EB; color: white }")) %>%
  prependContent(tags$style("table tr td:first-child { background-color: #ECE3FF }")) 
Enter fullscreen mode Exit fullscreen mode

Image description


🎨 Style: Image in Columns

In this section, we explore the enhancement of data representation by adding an image to an additional column. This approach provides an alternative method to elevate the visual impact of the data being presented. These images can serve as icons, represent brands, or convey additional visual elements to captivate and engage the audience.

library(flextable)

flextable(tmp_pivot%>%
              head(5)%>%
              mutate(id=0:4,
                     id=paste0('img/img_',id,'.png'))%>%
              select(c('id',names(tmp_pivot)))
         ) %>%
  colformat_image(j = "id", width = .5, height = 0.5) %>%
  bg(part = "header", bg = "#5E17EB", j =  c('id',names(tmp_pivot)) ) %>% 
  color(color = "white", part = "header") %>% 
  bg(part = "body", bg = "#ECE3FF")
Enter fullscreen mode Exit fullscreen mode

Image description


🎨 Style: Icons and Charts derived from column comparisons

In this section, we'll explore a creative approach using icons and charts to visually represent comparisons between two or more columns of data.

If you'd like to view the code for creating this style, it's available in my GitHub repository.

Feel free to check it out and give it a star if you find it helpful! ⭐️

GitHub logo r0mymendez / r-dataframe-styles

Add colors and styles to R DataFrames

Transform your R Dataframes: Styles, 🎨 Colors, and 😎 Emojis

In this repository, we will explore a method to add 🎨colors and πŸ–ŒοΈstyles in R DataFrames. We will focus on the application of colors and emojis, using approaches similar to the popular conditional formatting commonly used in pivot tables within spreadsheets. Through this strategy, we aim to improve the presentation of our data, making the exploration and understanding of the information not only informative but also visually attractive.

What libraries can I use to style my R dataframes?

The R libraries used to create this article are as follows:

libraries

Library Description
1. πŸ” tidyverse It integrates various R libraries for data manipulation, graphics, and analysis, promoting clear and efficient code.
2. πŸ“ knitr Automates the generation of dynamic reports.
3. πŸ“ kableExtra An additional extension that enhances table presentation in R Markdown documents with extra formatting options.
4. πŸ“„ reactablefrmtr
…

Image description

Image description

Image description

Image description

Image description


πŸ“š References

If you want to learn...

Top comments (0)