What are your preferred techniques for combining a table with a plot in one image using R? I remember using tableGrob() and either patchwork or cowplot months ago but cannot remember the details.
This example uses the ggstatsplot package. I would like to add the correlation coefficients to the correlogram (correlation plot).
if (!('ggstatsplot' %in% installed_packages)) {
devtools::install_github('https://github.com/IndrajeetPatil/ggstatsplot')
}
needed_pkgs <- setdiff(c('ggstatsplot', 'statsExpressions',
'dplyr', 'nnet', 'MASS'),
installed_packages)
if (length(needed_pkgs) > 0) {
install.packages(needed_pkgs)
}
library(ggstatsplot)
library(statsExpressions)
library(dplyr)
library(nnet)
library(MASS)
utils::example(topic = birthwt, echo = FALSE)
# model
bwt.mu <-
nnet::multinom(
formula = low ~ .,
data = bwt,
trace = FALSE
)
original_cols <- colnames(bwt)
bwt.mu_coefstats <- ggcoefstats(x = bwt.mu, output = "tidy") %>%
# skipping first row = intercept
slice(2:n()) %>%
dplyr::filter(term %in% original_cols) %>%
arrange(desc(p.value)) %>%
dplyr::select(term, estimate, p.value)
# Correlogram
cor_plot_out <-
ggstatsplot::ggcorrmat(bwt %>% dplyr::select(low, lwt, age))
Want to combine
bwt.mu_coefstats
cor_plot_out
The key elemnent is tableGrob() from gridExtra package!
We could use grid.arrange().
For the table use tableGrob() to create a table like the plot of a data frame. Then you can use it with grid.arrange() function.
library(gridExtra)
bwt.mu_coefstats <- tableGrob(
bwt.mu_coefstats,
theme = ttheme_default(
base_size = 10,
base_colour = "grey25",
parse = T
),
rows = NULL
)
grid.arrange(cor_plot_out, bwt.mu_coefstats,
heights = c(10, 4))
OR with patchwork:
library(patchwork)
cor_plot_out + bwt.mu_coefstats
I've been building my first applications in shiny in order to publish them and share interactive graphs with my coworkers. At present I've been producing density plots to map behaviour. The Goal is to display between 1 and 4 plots as facets, depending on the "origin" selection and the "variable" selection in shiny. If I manually plot all 4 graphs, I get an output resembling this:
sampleplot <- data.frame("origin" = c("US","GB","GB","US","CA","US","GB","GB","US","CA","US","GB","GB","US","CA","US","GB","GB","US","CA"),
"variable" = c("p1","p2","p3","p1","p4","p1","p2","p3","p1","p1","p1","p2","p3","p1","p4","p1","p2","p3","p1","p1"),
"value" = runif(20, min = 0.2, max = 0.8))
sampleplot %>%
ggplot(aes(value, color = origin)) +
facet_wrap(~ variable, ncol = 2) +
geom_density()
However, in shiny, when you select "p1", and then subsequently "p2", "p3" or "p4", the plot changes for "p1" (not just because of the scale, the shape is altered). It happens with any combination of variables. I get a warning along those lines when that happens:
Warning in ==.default(variable, input$var) :
longer object length is not a multiple of shorter object length
I don't get what the issue is. The variable checkbox input is every type of variable listed, and each facet is essentially an individual subplot. So why does plotting the density of "p2" have an impact on the density of "p1". Would be great if anyone could shine some line on the problem for me.
I made a reproducible shiny app with the data and ggplot call provided, and taking the change in scale apart, nothing rare happens. Let me know if it helps. It would be helpful if you can provide some code of your app, so we know exactly what's going with your plot.
Example app:
library(shiny)
library(tidyverse)
sampleplot <- data.frame("origin" = c("US","GB","GB","US","CA","US","GB","GB","US","CA","US","GB","GB","US","CA","US","GB","GB","US","CA"),
"variable" = c("p1","p2","p3","p1","p4","p1","p2","p3","p1","p1","p1","p2","p3","p1","p4","p1","p2","p3","p1","p1"),
"value" = runif(20, min = 0.2, max = 0.8))
ui <- fluidPage(sidebarLayout(
sidebarPanel(selectInput('selection', "Select sampleplot's variable",choices = unique(sampleplot$variable), multiple = TRUE, selected = 'p1')),
mainPanel(plotOutput('sameplots'))
)
)
server <- function(input, output, session) {
reactive_sameplot <- reactive({
sampleplot %>%
filter(variable %in% input$selection) %>%
ggplot(aes(value, color = origin)) +
facet_wrap(~ variable, ncol = 2) +
geom_density()
})
output$sameplots <- renderPlot({reactive_sameplot()})
}
shinyApp(ui, server)
I'm using the svars package to generate some IRF plots. The plots are rendered using ggplot2, however I need some help with changing some of the aesthetics.
Is there any way I can change the fill and alpha of the shaded confidence bands, as well as the color of the solid line? I know in ggplot2 you can pass fill and alpha arguments to geom_ribbon (and col to geom_line), just unsure of how to do the same within the plot function of this package's source code.
# Load Dataset and packages
library(tidyverse)
library(svars)
data(USA)
# Create SVAR Model
var.model <- vars::VAR(USA, lag.max = 10, ic = "AIC" )
svar.model <- id.chol(var.model)
# Wild Bootstrap
cores <- parallel::detectCores() - 1
boot.svar <- wild.boot(svar.model, n.ahead = 30, nboot = 500, nc = cores)
# Plot the IRFs
plot(boot.svar)
I'm also looking at the command for a historical decomposition plot (see below). Is there any way I could omit the first two facets and plot only the bottom three lines on the same facet?
hist.decomp <- hd(svar.model, series = 1)
plot(hist.decomp)
Your first desired result is easily achieved by resetting the aes_params after calling plot. For your second goal. There is probably an approach to manipulate the ggplot object. Instead my approach below constructs the plot from scratch. Basically I copy and pasted the data wrangling code from vars:::plot.hd and filtered the prepared dataset for the desired series:
# Plot the IRFs
p <- plot(boot.svar)
p$layers[[1]]$aes_params$fill <- "pink"
p$layers[[1]]$aes_params$alpha <- .5
p$layers[[2]]$aes_params$colour <- "green"
p
# Helper to convert to long dataframe. Source: svars:::plot.hd
hd2PlotData <- function(x) {
PlotData <- as.data.frame(x$hidec)
if (inherits(x$hidec, "ts")) {
tsStructure = attr(x$hidec, which = "tsp")
PlotData$Index <- seq(from = tsStructure[1], to = tsStructure[2],
by = 1/tsStructure[3])
PlotData$Index <- as.Date(yearmon(PlotData$Index))
}
else {
PlotData$Index <- 1:nrow(PlotData)
PlotData$V1 <- NULL
}
dat <- reshape2::melt(PlotData, id = "Index")
dat
}
hist.decomp <- hd(svar.model, series = 1)
dat <- hd2PlotData(hist.decomp)
dat %>%
filter(grepl("^Cum", variable)) %>%
ggplot(aes(x = Index, y = value, color = variable)) +
geom_line() +
xlab("Time") +
theme_bw()
EDIT One approach to change the facet labels is via a custom labeller function. For a different approach which changes the facet labels via the data see here:
myvec <- LETTERS[1:9]
mylabel <- function(labels, multi_line = TRUE) {
data.frame(variable = labels)
}
p + facet_wrap(~variable, labeller = my_labeller(my_labels))
I am trying to plot a heatmap with specified colors (by category) in plotly. I asked a similar question here: "Split" up by category in plotly.
However, I ran into a new problem while trying a similar thing with a heatmap. My code looks like:
# Test DataFrame
test_df <- data.frame(
"weekday" = c("Fr", "Sa", "Su"),
"time" = c("06:00:00", "12:00:00", "18:00:00"),
"channel" = c("NBC", "CBS Drama", "ABC"),
"colors" = c("#FCB711", "#162B48", "#AA8002"),
"views" = c(1200, 1000, 1250)
)
plot_ly(colors = unique(as.character(test_df$colors)), type = "heatmap") %>%
add_trace(test_df,
x = test_df$weekday,
y = test_df$time,
z = test_df$views,
type = "heatmap")
What I get is the following picture:
The problems I have here are:
1. The colors are not the colors which I told R to use
2. I do not want a colorscale, rather the categories split up channels.
I know there is a workaround in ggplot, and I am working on it, but I want to have it in plotly.
Here is what it looks like in ggplot and what I want to have in plotly (I am aware of ggplotly, but that still isn't pure plotly):
Here is the code for the above picture:
channel_colors <- test_df %>% distinct(colors) %>% pull(colors)
names(channel_colors) <- test_df %>% distinct(channel) %>% pull(channel)
p <- ggplot(data = test_df,
aes(
x = weekday,
y = time,
fill = channel)) +
geom_tile(aes(alpha = views)) +
scale_alpha(range = c(0.5, 1)) +
theme_minimal() +
scale_fill_manual(values = channel_colors)
ggplotly(p)
I would appreciate any help.
I am looking to make some kind of proportional squares (by lack of a better name) visualization in R. Example:
Any advice on how to do this in R (preferably ggplot2)?
This type of visualization is called a treemap. Appropriately, you can use the treemap package. You can find a detailed tutorial for treemap here but I'll show you the basics. Below I show you how to create a treemap in ggplot2 as well.
Treemap package
library(treemap)
cars <- mtcars
cars$carname <- rownames(cars)
treemap(
cars,
index = "carname",
vSize = "disp",
vColor = "cyl",
type = "value",
format.legend = list(scientific = FALSE, big.mark = " ")
)
ggplot2
There's also a developmental package on github for creating treemaps using ggplot2. Here's the repo for installing the package.
library(tidyverse)
library("ggfittext")
library("treemapify")
cars <- mtcars
cars$carname <- rownames(cars)
cars <- mutate(cars, cyl = factor(cyl))
ggplot(cars, aes(area = disp, fill = cyl, label = carname)) +
geom_treemap() +
geom_treemap_text(
fontface = "italic",
colour = "white",
place = "centre",
grow = TRUE
)