Uneven alignment in R formattable in combination with kableExtra - r

I'm failing to get left aligned numbers in kableExtra in combination with formattable's barplots in table cells.
Code to reproduce in rmarkdown format:
title: "Untitled"
output: html_document
knitr::opts_chunk$set(echo = TRUE)
library("formattable")
library("kableExtra")
Example
summary(cars)
cars$speed <- cars$speed * 100
Get a nice table
The table's first column is filled with tiny bar plots.
All code is written following http://haozhu233.github.io/kableExtra/awesome_table_in_html.html manual of kableExtra.
plot.table <- cars
# need to modify the first few values to make sure the effect is visible.
plot.table$speed[1] <- 3
plot.table$speed[2] <- 25
plot.table$speed[3] <- 100
plot.table$speed <- color_bar("lightgreen")(plot.table$speed)
kbl(x = plot.table,
escape = F) %>%
kable_styling(bootstrap_options = c("striped", "hover"), fixed_thead = T)
The first three rows show values that are small in comparison to the rest of the values in the table.
This makes theirs bars short and results in weirdly aligned numbers. The alignment is done according to the rightmost end of the green bar.
Inspecting the respective html element (e.g. FireFox "Inspect Element") reveals that the element "direction" is "rtl", which seems to be the default in kableExtra.
Manually modifying the value of this parameter to "ltr" yields nicely left aligned values extending across the bar's end.
Unfortunately, I couldn't find the parameter in color_bar to modify this behaviour.
Any help pointing me to a way to get the values left aligned would be highly appreciated.

as #juljo mentioned one obviously needs to modify the respective function. The body of the function could be copied out of the package contents.
f.color_bar <- function (color = "lightgray", fun = "proportion", ...)
{
fun <- match.fun(fun)
formattable::formatter("span", style = function(x) style(display = "inline-block",
direction = "ltr", `border-radius` = "4px",
`padding-right` = "2px", `background-color` = csscolor(color),
width = percent(fun(as.numeric(x), ...))))
}
This hard coded the left to right behaviour, but isn't variable here as well.

Related

How to display a table and its plot side by side with an adjusted height

I’m trying to display a table and its plot side by side in a page.
The goal is that the plot’s height matches with the table’s one !
I tried with st.container and st.columns combined but it does not work (see image below).
import streamlit as st
import plotly.express as px
long_df = px.data.medals_long()
fig = px.bar(long_df, x="nation", y="count",
color="medal", title="Long-Form Input")
data_container = st.container()
with data_container:
table, plot = st.columns(2)
with table:
st.table(long_df)
with plot:
st.plotly_chart(fig, use_container_width=True)
>>> Output (in the web browser):
As you can see, the plot is much longer than the table.
Do you know how to fix this, please ?
Important detail : I'm using different tables, so the number of rows is changing constantly.
Unfortunately, neither st.columns() nor st.container has a height parameter. You can achieve this using the height parameters of the plotly figure and st.dataframe(). When we define height for the dataframe, the user can scroll down to see whole table.
height = 400 # px
fig = px.bar(
long_df, x="nation", y="count",
color="medal", title="Long-Form Input",
height=height,
)
# update margin to show title on top
fig.update_layout(margin={"t": 30, "b": 0})
data_container = st.container()
with data_container:
table, plot = st.columns(2)
with table:
# use st.dataframe instead of st.table
st.dataframe(long_df, height=height)
with plot:
st.plotly_chart(fig, use_container_width=True)
Another way of visualising data along with the table is to use st.tabs().
tab1, tab2 = st.tabs(["Data", "Chart"])
with tab1:
st.table(long_df)
with tab2:
st.plotly_chart(fig, use_container_width=True)

Plots are squished when exporting to .pptx using officer

I'm using the officer package to write ggplots to Powerpoint, and even though my plots look good in my Rstudio viewer, my plots are getting "squished" when I add them to any custom slide with smaller content boxes.
I did my best to reproduce my issue with the following code:
library(tidyverse)
library(officer)
p <- data.frame(x = rnorm(100)) %>%
ggplot() +
geom_density(aes(x)) +
labs(title = "This is a title") +
annotate("text", x = 0, y = 0.2, label = "This is some text")
read_pptx("~/Downloads/template.pptx") %>%
add_slide(layout = "Title and Content") %>%
ph_with(p, location = ph_location_type("body", id = 1)) %>%
add_slide(layout = "text_example") %>%
ph_with(p, location = ph_location_type("body", id = 1)) %>%
print("~/Desktop/test_example.pptx")
Where template.pptx is a copy of the officer template with the "Title and Content" slide duplicated (and named "test_example") and content box shrunken down a little bit (available here for reproducibility).
The first slide looks good, like this:, but the second slide has the dimensions of the plot shrunken while the content in the plot stays the same size, giving it a "squished" feel:
Has anyone run into this before? Are there any tricks/hacks out there that can tell my plot to decrease the size of all it's elements when the total image space is decreased? I'd like to maintain the relative size of the elements of the plot as I move to different slide templates.
If you're still here - THANK YOU FOR READING SO FAR! I'd appreciate any and all tips :)
Here is the code that would avoid that problem with officer version 0.3.14 or later (I haven't update my package for a while and officer is an on-going package)
For better quality plot with smaller size using vector graphic instead. Using package rvg
library(rvg)
library(gridExtra)
document %<>%
add_slide(layout = "text_example") %>%
# add the plot in at position relative to 1 inches top left
# with size is 6 inches square
# grid.arrange is just a code for generate plot not actually arrange anything
ph_with(value = dml(code = grid.arrange(plot), bg = "transparent"),
location = ph_location(left=1, top=1, width=6,
height=6, bg="transparent")) %>%
# Add a text box on the right side of the slide with certain
# size & colors
ph_with(value = block_list(fpar(ftext(" "))),
location = ph_location(left=6.11, top=1, width=3.73,
height=3.3, bg="#C6D9F1"))
I would recommend this when working with Powerpoint otherwise, you need to adjust template in Powerpoint and remember the order of each content container in that slide

R plotly subplot add space between plots

I want to add space between plots but when I play with margin, it either overlaps or cuts.
Here is the code:
library(plotly)
plotList <- function(nplots) {
lapply(seq_len(nplots), function(x) plot_ly())
}
s1 <- subplot(plotList(6), nrows = 2, shareX = TRUE, shareY = TRUE)
s2 <- subplot(plotList(2), shareY = TRUE)
p <- subplot(s1, s2, plot_ly(), nrows = 3, margin = 0.04, heights = c(0.6, 0.3, 0.1))
print(p)
I obtain this:
Whereas i would rather like something like this (image done with paint) with more spacing between the different subplots:
How should I do ?
I was facing the same problem but, fortunately, I found a solution. You can use margin as an argument in Subplot function as follows:
subplot(plot1,
plot2,
nrows = 2,
margin = 0.07)
According to Plotly documentation, you can define only one or four values for each of the margins and those values should be between 0 and 1. If you provide only one value it will be used for all four margins or if you provide four values it will be used in the following order: the first one will be the left margin, the second one will be the right margin, the third one will be the top margin and the last one will be the bottom margin. You can play around and define the values that better fit the layout you want to create.
I found a solution by inserting blank plots between the normal plot. It is however a bit awkward but it works and I've found nothing better
blankplot<-plot_ly()%>%
layout(xaxis=list(visible="FALSE",color="white",tickfont =list(color="white")),
yaxis=list(visible="FALSE",color="white",tickfont =list(color="white")))

How to get flextable::vline to create single border

I want to display a single vertical border using the flextable package in R, but either I can't get it to work or there's a bug in the package (version 0.4.4):
library(flextable)
library(officer) # needed to define border properties
std_border = officer::fp_border(color="orange", width = 1)
# dataset to be used for examples
dat <- head(iris[c(1:5, 51:55, 101:105),])
ft <- regulartable(dat)
border_remove(x = ft)
# add internal borders
hline(ft, i = 3, border = std_border)
vline(ft, j = 3, border = std_border)
The result is this:
As intended, there is a horizontal line at the bottom of the third data row (starting with Sepal.Length = 4.700); so, hline seems to work as intended. However, I'm having trouble with vline: although there is a vertical line at the right edge of the Petal.Length column, there is also an undesired vertical line at the left edge of that column which I can't get rid of. I only want a single vertical line at the right edge of the specified column 3, which is what I understand to be the documented behaviour for vline.
Is this a bug in flextable 0.4.4 or could someone please help me figure out what I'm doing wrong?
This is an issue and has been solved in flextable 0.4.5.

How to place xtable object to the left side of page

Question: How to place xtable object to the left side of page or how to disable centering globally.
I'm struggling to figure out how to place xtable object on the left side. I have got a *.Rmd file and all this goes to the relevant r chunk.
require(xtable)
df <- data.frame(x=seq(1,10,1),y=rnorm(10))
Xtab <- xtable(df, digits=0, caption="\\textbf{MINIMAL/IDEAL}",
floating=FALSE, latex.environments = c("left"))
print(Xtab, size = "small", include.colnames=FALSE)
I have included the following after reading various sources (print.xtable; xtable manual etc.)
1) floating=FALSE
2) latex.environments = c("left")
I have searched SO and used some of the hints but all failed.
It seems to make quite a difference whether you pass a parameter to xtable() or to print(xtable()). The following chunk creates a table according to your data that is aligned at the left of the page in the pdf file.
```{r, results='asis',echo=FALSE}
library(xtable)
df <- data.frame(x=seq(1, 10, 1),y = rnorm(10))
print(xtable(df,digits=0, caption="\\textbf{MINIMAL/IDEAL}"), include.colnames=FALSE, size = "small", comment=FALSE, latex.environments="flushleft")
```
However, as you can see, the caption remains at the center of the page.

Resources