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:
π tidyverse: Among the best, it integrates various R libraries for data manipulation, graphics, and analysis, promoting clear and efficient code.
π knitr: Automates the generation of dynamic reports.
π kableExtra: An additional extension that enhances table presentation in R Markdown documents with extra formatting options.
π reactablefrmtr: Incorporates functions to craft interactive and flexible tables in R, featuring filtering, sorting, and search functionalities.
βοΈ htmltools: Offers functions to build and manipulate HTML objects in R.
π formattable: Equipped with functions for formatting and customizing tables in R.
π flextable: Another library enabling the creation of flexible and customizable tables in R, with advanced formatting options for documents and presentations.
π ggplot2: Among the most popular R visualization libraries, it produces appealing and comprehensible graphs.
π¨ 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.
π£ 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
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
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]))
[1] "tidyverse version: 1.3.1"
# 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 = ";")
π£ 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
Β π£ 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")
π¨ 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")
π¨ 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")
π¨ 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"))
π¨ 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
π¨ 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")
π¨ 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 }"))
π¨ 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")
π¨ 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! βοΈ
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:
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 |
π References
If you want to learn...
Top comments (0)