Tabelas no R
Meus pacotes do R favoritos para criar tabelas
Existem também muitos pacotes que fornecem funções para produzir tabelas bem formatadas.
Aqui estão os principais pacotes do R que conheço para produzir tabelas com boa aparência.
1. gt
O gt “é projetado para ser simples, mas poderoso … [com] ênfase em funções simples para as necessidades diárias para construção de tabelas.”
library(gt)
# Define the start and end dates for the data range
start_date <- "2010-06-02"
end_date <- "2010-06-15"
# The HTML decimal references for the black
# up- and down-pointing triangles are: #9650 and #9660;
# use an in-line style to apply color
up_arrow <- "<span style=\"color:green\">▲</span>"
down_arrow <- "<span style=\"color:red\">▼</span>"
# Create a gt table based on a preprocessed `sp500`
sp500 %>%
dplyr::filter(date >= start_date & date <= end_date) %>%
dplyr::select(-adj_close) %>%
gt() %>%
tab_header(
title = "S&P 500",
subtitle = glue::glue("{start_date} to {end_date}")
) %>%
fmt_date(
columns = vars(date),
date_style = 7
) %>%
fmt_currency(
columns = vars(open, high, low, close),
currency = "USD"
) %>%
fmt_number(
columns = vars(volume),
scale_by = 1 / 1E9,
pattern = "{x}B"
) %>%
text_transform(
locations = cells_body(
columns = "close",
rows = close > open),
fn = function(x) paste(x, up_arrow)
) %>%
text_transform(
locations = cells_body(
columns = "close",
rows = close < open),
fn = function(x) paste(x, down_arrow)
) %>%
cols_label(
date = "Date", open = "Open", high = "High",
low = "Low", close = "Close", volume = "Volume"
)
S&P 500 | |||||
---|---|---|---|---|---|
2010-06-02 to 2010-06-15 | |||||
Date | Open | High | Low | Close | Volume |
15 jun 2010 | $1,091.21 | $1,115.59 | $1,091.21 | $1,115.23 ▲ | 4.64B |
14 jun 2010 | $1,095.00 | $1,105.91 | $1,089.03 | $1,089.63 ▼ | 4.43B |
11 jun 2010 | $1,082.65 | $1,092.25 | $1,077.12 | $1,091.60 ▲ | 4.06B |
10 jun 2010 | $1,058.77 | $1,087.85 | $1,058.77 | $1,086.84 ▲ | 5.14B |
9 jun 2010 | $1,062.75 | $1,077.74 | $1,052.25 | $1,055.69 ▼ | 5.98B |
8 jun 2010 | $1,050.81 | $1,063.15 | $1,042.17 | $1,062.00 ▲ | 6.19B |
7 jun 2010 | $1,065.84 | $1,071.36 | $1,049.86 | $1,050.47 ▼ | 5.47B |
4 jun 2010 | $1,098.43 | $1,098.43 | $1,060.50 | $1,064.88 ▼ | 6.18B |
3 jun 2010 | $1,098.82 | $1,105.67 | $1,091.81 | $1,102.83 ▲ | 5.00B |
2 jun 2010 | $1,073.01 | $1,098.56 | $1,072.03 | $1,098.38 ▲ | 5.03B |
2. kable & kableExtra
O pacote kable é muito simples e sempre gera uma tabela. o kableExtra adiciona uma formatação.
library(knitr)
library(kableExtra)
data("iris")
vs_dt <- iris[1:10, ]
vs_dt[1:4] <- lapply(vs_dt[1:4], function(x) {
cell_spec(x, bold = T,
color = spec_color(x, end = 0.9),
font_size = spec_font_size(x))
})
vs_dt[5] <- cell_spec(vs_dt[[5]], color = "white", bold = T,
background = spec_color(1:10, end = 0.9, option = "A", direction = -1))
kable(vs_dt, escape = F, align = "c")
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
4.6 | 3.4 | 1.4 | 0.3 | setosa |
5 | 3.4 | 1.5 | 0.2 | setosa |
4.4 | 2.9 | 1.4 | 0.2 | setosa |
4.9 | 3.1 | 1.5 | 0.1 | setosa |
3. formattable
Esse é um dos pacotes favoritos para criar tabelas formatadas. Se você quer mexer no estilo, acho que esse é o pacote.
library(formattable)
df <- data.frame(
id = 1:10,
name = c("Bob", "Ashley", "James", "David", "Jenny",
"Hans", "Leo", "John", "Emily", "Lee"),
age = c(28, 27, 30, 28, 29, 29, 27, 27, 31, 30),
grade = c("C", "A", "A", "C", "B", "B", "B", "A", "C", "C"),
test1_score = c(8.9, 9.5, 9.6, 8.9, 9.1, 9.3, 9.3, 9.9, 8.5, 8.6),
test2_score = c(9.1, 9.1, 9.2, 9.1, 8.9, 8.5, 9.2, 9.3, 9.1, 8.8),
final_score = c(9, 9.3, 9.4, 9, 9, 8.9, 9.25, 9.6, 8.8, 8.7),
registered = c(TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE),
stringsAsFactors = FALSE)
formattable(df, list(
age = color_tile("white", "orange"),
grade = formatter("span", style = x ~ ifelse(x == "A",
style(color = "green", font.weight = "bold"), NA)),
area(col = c(test1_score, test2_score)) ~ normalize_bar("pink", 0.2),
final_score = formatter("span",
style = x ~ style(color = ifelse(rank(-x) <= 3, "green", "gray")),
x ~ sprintf("%.2f (rank: %02d)", x, rank(-x))),
registered = formatter("span",
style = x ~ style(color = ifelse(x, "green", "red")),
x ~ icontext(ifelse(x, "ok", "remove"), ifelse(x, "Yes", "No")))
))
id | name | age | grade | test1_score | test2_score | final_score | registered |
---|---|---|---|---|---|---|---|
1 | Bob | 28 | C | 8.9 | 9.1 | 9.00 (rank: 06) | Yes |
2 | Ashley | 27 | A | 9.5 | 9.1 | 9.30 (rank: 03) | No |
3 | James | 30 | A | 9.6 | 9.2 | 9.40 (rank: 02) | Yes |
4 | David | 28 | C | 8.9 | 9.1 | 9.00 (rank: 06) | No |
5 | Jenny | 29 | B | 9.1 | 8.9 | 9.00 (rank: 06) | Yes |
6 | Hans | 29 | B | 9.3 | 8.5 | 8.90 (rank: 08) | Yes |
7 | Leo | 27 | B | 9.3 | 9.2 | 9.25 (rank: 04) | Yes |
8 | John | 27 | A | 9.9 | 9.3 | 9.60 (rank: 01) | No |
9 | Emily | 31 | C | 8.5 | 9.1 | 8.80 (rank: 09) | No |
10 | Lee | 30 | C | 8.6 | 8.8 | 8.70 (rank: 10) | No |
4. DT
O pacote DT permite criar tabelas paginadas, ferramentas para download e filtros.
library(DT)
datatable(head(iris), colnames = c('Aqui', 'Temos', 'os nomes', 'das', 'variaveis'))
datatable(
head(iris), extensions = 'Buttons', options = list(
dom = 'Bfrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
)
)
m = matrix(c(
'<b>Bold</b>', '<em>Emphasize</em>', '<a href="http://rstudio.com">RStudio</a>',
'<a href="#" onclick="alert(\'Hello World\');">Hello</a>'
), 2)
colnames(m) = c('<span style="color:red">Column 1</span>', '<em>Column 2</em>')
#datatable(m) # escape = TRUE by default
datatable(m, escape = FALSE)
datatable(
iris,
options = list(dom = 'Pfrtip', columnDefs = list(list(
searchPanes = list(show = FALSE), targets = 1:4
))),
extensions = c('Select', 'SearchPanes'),
selection = 'none'
)
5. reactable
Esse pacote criou a tabela mais bonita que eu já vi no RMarkdown. Vou reproduzi-la abaixo.
library(reactable)
library(htmltools)
forecasts <- read.csv("C:/Users/Hp/Documents/GitHub/Base_de_dados/wwc_forecasts.csv", stringsAsFactors = FALSE)
rating_cols <- c("spi", "global_o", "global_d")
group_cols <- c("group_1", "group_2", "group_3")
knockout_cols <- c("make_round_of_16", "make_quarters", "make_semis", "make_final", "win_league")
forecasts <- forecasts[, c("team", "points", "group", rating_cols, group_cols, knockout_cols)]
rating_column <- function(maxWidth = 55, ...) {
colDef(maxWidth = maxWidth, align = "center", class = "cell number", ...)
}
group_column <- function(class = NULL, ...) {
colDef(cell = format_pct, maxWidth = 70, align = "center", class = paste("cell number", class), ...)
}
knockout_column <- function(maxWidth = 70, class = NULL, ...) {
colDef(
cell = format_pct,
maxWidth = maxWidth,
class = paste("cell number", class),
style = function(value) {
# Lighter color for <1%
if (value < 0.01) {
list(color = "#aaa")
} else {
list(color = "#111", background = knockout_pct_color(value))
}
},
...
)
}
format_pct <- function(value) {
if (value == 0) " \u2013 " # en dash for 0%
else if (value == 1) "\u2713" # checkmark for 100%
else if (value < 0.01) " <1%"
else if (value > 0.99) ">99%"
else formatC(paste0(round(value * 100), "%"), width = 4)
}
make_color_pal <- function(colors, bias = 1) {
get_color <- colorRamp(colors, bias = bias)
function(x) rgb(get_color(x), maxColorValue = 255)
}
off_rating_color <- make_color_pal(c("#ff2700", "#f8fcf8", "#44ab43"), bias = 1.3)
def_rating_color <- make_color_pal(c("#ff2700", "#f8fcf8", "#44ab43"), bias = 0.6)
knockout_pct_color <- make_color_pal(c("#ffffff", "#f2fbd2", "#c9ecb4", "#93d3ab", "#35b0ab"), bias = 2)
tbl <- reactable(
forecasts,
pagination = FALSE,
defaultSorted = "win_league",
defaultSortOrder = "desc",
defaultColGroup = colGroup(headerClass = "group-header"),
columnGroups = list(
colGroup(name = "Team Rating", columns = rating_cols),
colGroup(name = "Chance of Finishing Group Stage In ...", columns = group_cols),
colGroup(name = "Knockout Stage Chances", columns = knockout_cols)
),
defaultColDef = colDef(class = "cell", headerClass = "header"),
columns = list(
team = colDef(
defaultSortOrder = "asc",
minWidth = 200,
headerStyle = list(fontWeight = 700),
cell = function(value, index) {
div(
class = "team",
img(class = "flag", alt = paste(value, "flag"), src = sprintf("C:/Users/Hp/Documents/GitHub/blog/tables-in-r/images/%s.png", value)),
div(class = "team-name", value),
div(class = "record", sprintf("%s pts.", forecasts[index, "points"]))
)
}
),
points = colDef(show = FALSE),
group = colDef(defaultSortOrder = "asc", align = "center", maxWidth = 75,
class = "cell group", headerStyle = list(fontWeight = 700)),
spi = rating_column(format = colFormat(digits = 1)),
global_o = rating_column(
name = "Off.",
cell = function(value) {
scaled <- (value - min(forecasts$global_o)) / (max(forecasts$global_o) - min(forecasts$global_o))
color <- off_rating_color(scaled)
value <- format(round(value, 1), nsmall = 1)
div(class = "spi-rating", style = list(background = color), value)
}
),
global_d = rating_column(
name = "Def.",
defaultSortOrder = "asc",
cell = function(value) {
scaled <- 1 - (value - min(forecasts$global_d)) / (max(forecasts$global_d) - min(forecasts$global_d))
color <- def_rating_color(scaled)
value <- format(round(value, 1), nsmall = 1)
div(class = "spi-rating", style = list(background = color), value)
}
),
group_1 = group_column(name = "1st Place", class = "border-left"),
group_2 = group_column(name = "2nd Place"),
group_3 = group_column(name = "3rd Place"),
make_round_of_16 = knockout_column(name = "Make Round of 16", class = "border-left"),
make_quarters = knockout_column(name = "Make Qtr-Finals"),
make_semis = knockout_column(name = "Make Semifinals", maxWidth = 90),
make_final = knockout_column(name = "Make Final"),
win_league = knockout_column(name = "Win World Cup")
),
# Emphasize borders between groups when sorting by group
rowClass = JS("
function(rowInfo, state) {
const firstSorted = state.sorted[0]
if (firstSorted && firstSorted.id === 'group') {
const nextRow = state.pageRows[rowInfo.viewIndex + 1]
if (nextRow && rowInfo.row.group !== nextRow.group) {
return 'group-last'
}
}
}"
),
showSortIcon = FALSE,
borderless = TRUE,
class = "standings-table"
)
div(class = "standings",
div(class = "title",
h2("2019 Women's World Cup Predictions"),
"Soccer Power Index (SPI) ratings and chances of advancing for every team"
),
tbl,
"Forecast from before 3rd group matches"
)
2019 Women's World Cup Predictions
Soccer Power Index (SPI) ratings and chances of advancing for every team6. flextable
dat <- tibble::tribble(
~namePlayer, ~ratioBPM, ~ratioOBPM, ~ratioDBPM, ~urlPlayerStats, ~urlPlayerHeadshot,
"James Harden", 11.7, 10.5, 1.1, "https://stats.nba.com/player/201935", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/201935.png",
"Giannis Antetokounmpo", 10.8, 5.7, 5, "https://stats.nba.com/player/203507", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/203507.png",
"Nikola Jokic", 9.5, 5.7, 3.8, "https://stats.nba.com/player/203999", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/203999.png",
"Anthony Davis", 8.5, 4.7, 3.9, "https://stats.nba.com/player/203076", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/203076.png",
"LeBron James", 8.1, 6.2, 1.9, "https://stats.nba.com/player/2544", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/2544.png",
"Rudy Gobert", 7, 2, 5.1, "https://stats.nba.com/player/203497", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/203497.png",
"Karl-Anthony Towns", 6.8, 4.8, 2, "https://stats.nba.com/player/1626157", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/1626157.png",
"Russell Westbrook", 6.5, 2.5, 3.9, "https://stats.nba.com/player/201566", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/201566.png",
"Kyrie Irving", 6.4, 6, 0.4, "https://stats.nba.com/player/202681", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/202681.png",
"Nikola Vucevic", 6.4, 3, 3.4, "https://stats.nba.com/player/202696", "https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/202696.png"
)
library(flextable)
ft <- flextable(dat, cwidth = c(1.7, .7, .7, .7, 1, .7)) %>%
flextable::add_header_lines("Top 10 Box Plus/Minus") %>%
set_header_labels(namePlayer = "", ratioBPM = "BPM", ratioOBPM = "OBPM",
ratioDBPM = "DBPM", urlPlayerStats = "Link", urlPlayerHeadshot = "") %>%
compose( j = "urlPlayerStats",
value = as_paragraph( hyperlink_text(x = "player stats", url = urlPlayerStats ) ) ) %>%
compose( j = "urlPlayerHeadshot",
value = as_paragraph(
as_image(src = urlPlayerHeadshot, width = .52, height = .38)
), part = "body") %>%
footnote( i = 1, j = 1, ref_symbols = "*",
value = as_paragraph("Players with 500+ minutes."), part = "header") %>%
footnote( i = 2, j = 2:4, ref_symbols = c("†", "‡", "§"),
value = as_paragraph(
c("Box Plus/Minus: a box score estimate of the points per 100 possessions that a player contributed above a league-average player, translated to an average team.",
"Offensive Box Plus/Minus.", "Defensive Box Plus/Minus.")
), part = "header") %>%
theme_zebra(odd_header="transparent") %>%
valign(valign = "bottom", part = "all") %>%
fontsize(i = 1, part = "header", size = 20) %>%
bold(i = 1, part = "header", bold = TRUE) %>%
bold(part = "footer", bold = FALSE) %>%
italic(part = "footer", italic = TRUE) %>%
color(j = 5, color = "#337ab7") %>%
vline(j = 1, part = "body", border = officer::fp_border()) %>%
border_inner_h(part = "header", border = officer::fp_border()) %>%
hline_bottom(part = "all", border = officer::fp_border()) %>%
colformat_num(col_keys = c("ratioBPM", "ratioOBPM", "ratioDBPM"), digits = 1 )
ft
Top 10 Box Plus/Minus* | |||||
BPM† | OBPM‡ | DBPM§ | Link | ||
James Harden | 11.7 | 10.5 | 1.1 | ||
Giannis Antetokounmpo | 10.8 | 5.7 | 5.0 | ||
Nikola Jokic | 9.5 | 5.7 | 3.8 | ||
Anthony Davis | 8.5 | 4.7 | 3.9 | ||
LeBron James | 8.1 | 6.2 | 1.9 | ||
Rudy Gobert | 7.0 | 2.0 | 5.1 | ||
Karl-Anthony Towns | 6.8 | 4.8 | 2.0 | ||
Russell Westbrook | 6.5 | 2.5 | 3.9 | ||
Kyrie Irving | 6.4 | 6.0 | 0.4 | ||
Nikola Vucevic | 6.4 | 3.0 | 3.4 | ||
*Players with 500+ minutes. | |||||
†Box Plus/Minus: a box score estimate of the points per 100 possessions that a player contributed above a league-average player, translated to an average team. | |||||
‡Offensive Box Plus/Minus. | |||||
§Defensive Box Plus/Minus. |
7. huxtable
Esse é o melhor pacote para tabelas no LaTeX e criação de pdfs.
library(huxtable)
data(mtcars)
carros<-head(mtcars)
car_ht <- as_hux(carros)
lego_hux <- as_hux(carros) %>%
set_background_color(1:2, 1:2, "red") %>%
set_background_color(1:2, 3:4, "yellow") %>%
set_background_color(3:4, 1:2, "darkgreen") %>%
set_background_color(3:4, 3:4, "blue") %>%
set_text_color(3:4, 1:4, "white") %>%
set_all_borders(brdr(2, "solid", "white"))
lego_hux %>% set_caption("Original table")
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb |
---|---|---|---|---|---|---|---|---|---|---|
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.5 | 0 | 1 | 4 | 4 |
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17 | 0 | 1 | 4 | 4 |
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.6 | 1 | 1 | 4 | 1 |
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.4 | 1 | 0 | 3 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17 | 0 | 0 | 3 | 2 |
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.2 | 1 | 0 | 3 | 1 |
car_ht %>%
set_width(0.8) %>%
set_font_size(8) %>%
set_lr_padding(2) %>%
set_col_width(rep(c(0.4, 0.2, 0.2, 0.2, 0.2), 3)/3) %>%
set_position("left")
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb |
---|---|---|---|---|---|---|---|---|---|---|
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.5 | 0 | 1 | 4 | 4 |
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17 | 0 | 1 | 4 | 4 |
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.6 | 1 | 1 | 4 | 1 |
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.4 | 1 | 0 | 3 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17 | 0 | 0 | 3 | 2 |
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.2 | 1 | 0 | 3 | 1 |
8. Rhandsomtable
library(rhandsontable)
DF = data.frame(
title = c(
"<a href='http://www.amazon.com/Professional-JavaScript-Developers-Nicholas-Zakas/dp/1118026691'>Professional JavaScript for Web Developers</a>",
"<a href='http://shop.oreilly.com/product/9780596517748.do'>JavaScript: The Good Parts</a>",
"<a href='http://shop.oreilly.com/product/9780596805531.do'>JavaScript: The Definitive Guide</a>"
),
desc = c(
"This <a href='http://bit.ly/sM1bDf'>book</a> provides a developer-level introduction along with more advanced and useful features of <b>JavaScript</b>.",
"This book provides a developer-level introduction along with <b>more advanced</b> and useful features of JavaScript.",
"<em>JavaScript: The Definitive Guide</em> provides a thorough description of the core <b>JavaScript</b> language and both the legacy and standard DOMs implemented in web browsers."
),
comments = c(
"I would rate it ★★★★☆",
"This is the book about JavaScript",
"I've never actually read it, but the <a href='http://shop.oreilly.com/product/9780596805531.do'>comments</a> are highly <strong>positive</strong>."
),
cover = c(
"http://ecx.images-amazon.com/images/I/51bRhyVTVGL._SL50_.jpg",
"http://ecx.images-amazon.com/images/I/51gdVAEfPUL._SL50_.jpg",
"http://ecx.images-amazon.com/images/I/51VFNL4T7kL._SL50_.jpg"
),
stringsAsFactors = FALSE
)
rhandsontable(DF, allowedTags = "<em><b><strong><a><big>",
width = 800, height = 450, rowHeaders = FALSE) %>%
hot_cols(colWidths = c(200, 200, 200, 80)) %>%
hot_col(1:2, renderer = "html") %>%
hot_col(1:3, renderer = htmlwidgets::JS("safeHtmlRenderer")) %>%
hot_col(4, renderer = "
function(instance, td, row, col, prop, value, cellProperties) {
var escaped = Handsontable.helper.stringify(value),
img;
if (escaped.indexOf('http') === 0) {
img = document.createElement('IMG');
img.src = value;
Handsontable.dom.addEvent(img, 'mousedown', function (e){
e.preventDefault(); // prevent selection quirk
});
Handsontable.dom.empty(td);
td.appendChild(img);
}
else {
// render as text
Handsontable.renderers.TextRenderer.apply(this, arguments);
}
return td;
}")
Esses são os principais. Tem muito mais.
Os pacotes pander, pixiedust, ztable, condformat, xtable, flexpivot, e stargazer também são interessantes.