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

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)

Related

how to combine multiple html files with plots with same width and height

Here i tried to combine 2 html world maps as plots but they are combined within 2 rows and the size i.e., height of the plots is reduced, but since i am combining them as html i expect that the we can scroll the html so the plots should be displayed with full width and height as they appear as original.
the gplot1 and gplot2 are 2 ggplotly graphs
gplot1 <- ggplotly(gplot, tooltip = "text")
gplot2 <- ggplotly(gplot, tooltip = "text")
manipulateWidget::combineWidgets(title = "Location of PHUSE Global Events 2022 & 2023",
gplot1, gplot2,
byrow = T
)
The single html appears as below
whereas the 2 html combined with htmlwidget appears as below

Highlight a Specific Section of a Treemap using Treemap package in R

I am using the Treemap package in R to highlight the number of COVID outbreaks in different settings. I am making a number of different reports using R Markdown. Each one describes a different type of settings and I would like to highlight that setting in the treemap for each report, showing what proportion of total outbreaks occur in the setting in question. For example you I am currently working on the K-12 school report and would like to highlight the box representing that category in the figure.
I was previously using an exploded donut pie chart however there were two many subcategories and the graph became hard to read.
I am picturing a way to change the label or border on one specific box, ie. put a yellow border around the box or make the label yellow. I found a way to do both these things for all the boxes but not just one specific box. I made this image using the snipping tool to further illustrate what the desired outcome might look like. The code to generate the treemap can be found in the link below. It looks like this:
# library
library(treemap)
# Build Dataset
group <- c(rep("group-1",4),rep("group-2",2),rep("group-3",3))
subgroup <- paste("subgroup" , c(1,2,3,4,1,2,1,2,3), sep="-")
value <- c(13,5,22,12,11,7,3,1,23)
data <- data.frame(group,subgroup,value)
# treemap
treemap(data,
index=c("group","subgroup"),
vSize="value",
type="index"
)
This is the most straightforward information I can find about the package, this is where I took the sample image and code from: https://www.r-graph-gallery.com/236-custom-your-treemap.html
It looks like the treemap package doesn't have a built-in way to do this. But we can hack it by using the data frame returned by treemap() and adding a rectangle to the appropriate viewport.
# Plot the treemap and save the data used for plotting.
t = treemap(data,
index = c("group", "subgroup"),
vSize = "value",
type = "index"
)
# Add a rectangle around subgroup-2.
library(grid)
library(dplyr)
with(
# t$tm is a data frame with one row per rectangle. Filter to the group we
# want to highlight.
t$tm %>%
filter(group == "group-1",
subgroup == "subgroup-2"),
{
# Use grid.rect to add a rectangle on top of the treemap.
grid.rect(x = x0 + (w / 2),
y = y0 + (h / 2),
width = w,
height = h,
gp = gpar(col = "yellow", fill = NA, lwd = 4),
vp = "data")
}
)

Uneven alignment in R formattable in combination with kableExtra

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.

heatmap in R how to resize columns labels?

I have a data.matrix that is approximately 4000 rows and 100 columns. I am doing a heatmap of the data like:
data<-heatmap(data_matrix,Rowv=NA,Colv=NA,col=cm.colors(256),scale="column",margins=c(5,10))
But the problem that I got is that the labels that appear in the column are too grouped, so it is impossible to visualize them correctly. How I can resize the heatmap so I can see the values of the labels of the column? I tried to print it in pdf, but it only appears a black stripe.
Thanks
I am including a figure of the heatmap, the portion that I want to see are the labels that are in the right part, but they are too close together.
First of all it's better to put your output directly to a PDF file - you may use other image formats but PDF is the best because it is a vector output and you can zoom as much as you want:
pdf("Your-file.pdf", paper="a4", width=8, height=8)
Then it's better to use pheatmap( = pretty heatmap) package. It makes really better heatmaps with a color key besides your heatmap. Finally although the pheatmap() function tries to reduce the label size while you have many rows, but it fails for really large number of rows. So I use the code below for really high - but not too high - number of rows:
library(pheatmap)
library(gplots)
if (nrow(table) > 100) stop("Too many rows for heatmap, who can read?!")
fontsize_row = 10 - nrow(table) / 15
pheatmap(table, col=greenred(256), main="My Heatmap", cluster_cols=F,
fontsize_row=fontsize_row, border_color=NA)
You may change fontsize_col for the column labels. You have many interesting options like display_numbers to have the values inside the cells of your heatmap. Just read ?pheatmap.
This is an example generated by the default parameters of pheatmap() command:
Finally note that too many rows are easy to read on a display, but useless for print.
In Rstudio you can easily resize the graphic window, same holds for Rgui. Alternatively, if you save the plot to file you can use a bigger size for your graphics, e.g. bigger width and height when calling pdf or png.
You can use cexRow = and cexCol =.
You can get more information into ??heatmap.2
# Row/Column Labeling
margins = c(5, 5),
ColSideColors,
RowSideColors,
cexRow = 0.2 + 1/log10(nr),
cexCol = 0.2 + 1/log10(nc),
labRow = NULL,
labCol = NULL,
srtRow = NULL,
srtCol = NULL,
adjRow = c(0,NA),
adjCol = c(NA,0),
offsetRow = 0.5,
offsetCol = 0.5,
colRow = NULL,
colCol = NULL
If you use pheatmap (https://www.rdocumentation.org/packages/COMPASS/versions/1.10.2/topics/pheatmap) you can spread out those labels by adjusting the cellheight parameter.
If you are doing this in R notebook, even though the entire heat map will not display in your output window when you run the code, when you save the heat map to your computer using the filename parameter, pheatmap will automatically calculate the optimal size for the output file so that your entire heatmap will be displayed in your output file. If this size is not to your liking you can adjust using width and height parameters, but it is unlikely you will want to do this.

aligning patterns across panels with gridExtra and grid.pattern()

The gridExtra package adds a grob of class "pattern" that lets one fill rectangles with patterns. For example,
library(gridExtra)
grid.pattern(pattern = 1)
creates a box filled with diagonal lines. I want to create a stack of panels in which each panel is filled with these diagonal lines. This is easy:
library(lattice); library(gridExtra)
examplePlot <- xyplot(
1 ~ 1 | 1:2,
panel = function () grid.pattern(pattern = 1),
layout = c(1, 2),
# Remove distracting visual detail
scales = list(x=list(draw=FALSE), y=list(draw=FALSE)),
strip = FALSE, xlab = '', ylab = ''
)
print(examplePlot)
The problem is that the diagonal lines aren't aligned across panels. That is, there is a visual "break" where the bottom of the first panel meets the top of the second panel: at that point, the lines don't line up. This is the problem that I want to fix.
I can eliminate most of the visual break by adding the argument pattern.offset = c(.2005, 0) to the grid.pattern call, and making sure that it applies only to the bottom panel. But this solution doesn't generalize. For example, if I change the pattern (e.g., by using the granularity argument to grid.pattern), this solution won't work. Is there a more general fix?
To make this work, you'll have to take charge of setting the panel.height argument used by print.trellis. (To see why, try resizing your plotting device after running your example code: as the size of the device and the panels changes, so does the matching/mismatching of the lines):
## Calculate vertical distance (in mm) between 45 degree diagonal lines
## spaced 5mm apart (the default distance for grid.pattern).
vdist <- 5 * sqrt(2)
nLines <- 8L ## can be any integer
panelHeight <- list(x = nLines*vdist, units = "mm", data = NULL)
## Plot it
print(examplePlot, panel.height=panelHeight)

Resources