Custom colors in ggplot2 subtitle feat. crayon and glue - r

I'd like to create a subtitle with a few custom colored words in ggplot2. We can use crayon::make_style, glue::glue, and glue::glue_col to make this happen in the console (see below). However, when implementing in the graphics device, the color doesn't render. I looked through the source code for a hint but failed to find one. Any thoughts?
library(glue)
library(crayon)
library(tidyverse)
# create data frame
myDat <- tibble(alpha = rnorm(50),
omega = runif(50))
# use crayon to create our custom colors
slate_g <- crayon::make_style("slategrey")
light_s <- make_style("lightsalmon")
# create custom subtitle NOTE it prints cleanly in the console
cust_subt <- glue("
{str_wrap(\"It is a wonder that this subtitle is so dangerously long. Good thing we can wrap it in glue.\", 75)}
Really makes me wonder
{glue_col(\'{bold({slate_g(\"NEVER\")})} vs. {bold({light_s(\"ENOUGH\")})}\')}
")
Here is how the cust_subt object prints in the console.
Once we try to plot, though, it fails.
# custom subtitle DOES NOT work in subtitle
ggplot(myDat, aes(alpha, omega)) +
geom_point() +
labs(subtitle = cust_subt)
#### regular glue works just fine though
cust_subt_no_col <- glue("
{str_wrap(\"It is a wonder that this subtitle is so dangerously long. Good thing we can wrap it in glue.\", 75)}
Really makes me wonder
")
ggplot(myDat, aes(alpha, omega)) +
geom_point() +
labs(subtitle = cust_subt_no_col)

Related

R patchwork package trouble displaying many plots

I am enjoying the patchwork package quite a bit and I am generally happy with even its default formatting.
However, I cannot figure out how to get a reasonable result when trying to display many plots. The output is unreadable (plots shrunk down and dominated by text) and the saved output is completely blank.
Input:
require(ggplot2)
require(patchwork)
plots <- list()
testfunction <- function(x) {
plot_placeholder <- ggplot(mtcars) +
geom_point(aes(mpg, disp)) +
ggtitle(paste("p", x, sep = ""))
plots[[length(plots) + 1]] <<- plot_placeholder
}
mapply(testfunction, c(1:66), SIMPLIFY = FALSE)
patchwork::wrap_plots(plots)
ggsave("test.pdf")
Output:
Is there a way within patchwork to make the page larger or wrap plots across multiple pages of a PDF? Or is there a different package that may help with this?
Update:
Maurits Evers pointed out that this is an issue with my arguments in ggsave(), not patchwork. With these changes the plots look much better in the .pdf output, but were still being truncated at the bottom of page 1. From this post, found the last bit of change needed to generate desired results
Input:
# ...
pdf()
patchwork::wrap_plots(plots)
ggsave("test.pdf", width = 20, height = 20)
dev.off()
Output:

Automatic line break in ggtitle

Is there a way to force an automatic line break in the ggtitle command?
As part of a shiny application I use different plots with an input variable for the title.
Unfortunately, some of these variable values are too long to be displayed.
I came across one possibility by inserting \n (or a line break) manually in advance (Details here: Improve editing of multiline title in ggplot that uses \n and extends far to the right). There, something like ggtitle(paste("", title, "", sep = "\n")) would be suggested.
Since including \n would be error prone as well as not flexible for different plot sizes I´m looking for another possibility.
Here is an minimal working example (adapted from lawyeR question linked above):
DF <- data.frame(x = rnorm(400))
title_example <- "This is a very long title describing the plot in its details. The title should be fitted to a graph, which is itself not restricted by its size."
plot <- ggplot(DF, aes(x = x)) + geom_histogram() +
ggtitle(title_example)
You can find a image here: https://i.stack.imgur.com/6MMKF.jpg
Do you have an idea how to e.g. adapt the sep = operator to break lines automatically or are there maybe packages/ workarounds? Thanks!
The ggtext package's text elements could help solve this. element_textbox_simple() automatically wraps the text inside. Try resizing the graphics device window, it adapts!
library(ggplot2)
library(ggtext)
DF <- data.frame(x = rnorm(400))
title_example <- "This is a very long title describing the plot in its details. The title should be fitted to a graph, which is itself not restricted by its size."
ggplot(DF, aes(x = x)) + geom_histogram() +
ggtitle(title_example) +
theme(plot.title = element_textbox_simple())
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Changing 'likert' standard texts

I don't know how to change the standard texts on plots created using the likert package.
To make it easy, i will just provide the sample data, as the solution probably will be the same.
library(likert)
data(pisaitems)
items28 <- pisaitems[, substr(names(pisaitems), 1, 5) == "ST24Q"]
l28 <- likert(items28)
plot(l28)
The output should be as the picture below, and what i want to change are the words "Response" and "Percentage."
Hope you can help!
Welcome to SO! I did not know the likert package but, it seems that its function plot, is based on ggplot2, so you can modify the options in ggplot2 way:
plot(l28) +
labs(
x = "Another lab", # here you manage axis
y = "My lab" # also here ("inverted "because
# it seems plot has coord_flip option)
) + guides(fill=guide_legend("My e title")) # here you manage the title of the legend

R open plotly in standalone window

I would like to display a plotly plot object in a standalone window that behaves similarly to the window that pops up using the base R plot() function.
Using a basic example from the plotly website:
library(ggplot2)
library(plotly)
d <- diamonds[sample(nrow(diamonds), 1000), ]
p <- ggplot(data = d, aes(x = carat, y = price)) +
geom_point(aes(text = paste("Clarity:", clarity))) +
geom_smooth(aes(colour = cut, fill = cut)) + facet_wrap(~ cut)
p2 <- ggplotly(p)
The p2 object is an htmlwidget object and I get some control over its display using the sizingPolicy element as described here. However, I can't find anything that allows me to set the viewer/browser to something other than my current browser (as a new tab) or within RStudio.
Ideally, I'd like to avoid applications outside of R packages to launch a separate window from within R. However, I would also be happy with figuring out how to granularly control browser output to display p2 as a new window in kiosk or app mode (see the answers to this question for some examples of kiosk/app mode).
Edit: Although I mentioned RStudio when discussing some of the options that I was able to find, I am talking about using R from a simple console. That said, granular display options should hopefully be independent of the user interface.
I have a working solution, but I'll be happy to change the accepted answer if someone has anything better.
I defined a print function that can be used to launch a custom browser command for an htmlwidget object. In this case, I used chromium-browser -app=..., but the overall approach should be general.
print_app <- function(widget) {
# Generate random file name
temp <- paste(tempfile('plotly'), 'html', sep = '.')
# Save. Note, leaving selfcontained=TRUE created files that froze my browser
htmlwidgets::saveWidget(widget, temp, selfcontained = FALSE)
# Launch with desired application
system(sprintf("chromium-browser -app=file://%s", temp))
# Return file name if it's needed for any other purpose
temp
}
Combining with the previous example:
library(ggplot2)
library(plotly)
d <- diamonds[sample(nrow(diamonds), 1000), ]
p <- ggplot(data = d, aes(x = carat, y = price)) +
geom_point(aes(text = paste("Clarity:", clarity))) +
geom_smooth(aes(colour = cut, fill = cut)) + facet_wrap(~ cut)
p2 <- ggplotly(p)
print_app(p2)
It seems like htmlwidgets normally uses the html_print function from htmltools, which in turn selects the browser to use via getOption("viewer", utils::browseURL), which bakes in a lot of the browser selection options -- making it challenging to change.
The idea for saving the html file locally came from this plotly issue: saving plotly plots locally?.
If you are using MacOS, change this line in #ssokolen's answer
# Launch with desired application
system(sprintf("chromium-browser -app=file://%s", temp))
to
system(sprintf("open -a 'google chrome' /%s", temp))
Works in zsh in MacOs Catalina with the Intellij R plugin.

How to furnish a ggplot2 figure with a hyperlink?

I am trying to furnish a ggplot2 plot with a hyperlink:
This works:
library(gridSVG)
library(lattice)
xyplot(mpg~wt, data=mtcars, main = "Link to R-project home")
mainGrobName <- grep("main", grid.ls()[[1]], value=TRUE)
grid.hyperlink(mainGrobName, "http://www.r-project.org")
gridToSVG("HyperlinkExample.svg")
This not:
p = ggplot(mtcars, aes(wt, mpg)) + geom_point()+ labs(title="link")
print(p)
mainGrobName <- grep("title", grid.ls()[[1]], value=TRUE)
grid.hyperlink(mainGrobName, "http://www.r-project.org")
gridToSVG("HyperlinkExample.svg")
Any hints on this?
I have asked Simon Potter, one of the authors of the gridSVG package:
Here is his (working) answer:
I suggest you try the development version here:
http://r-forge.r-project.org/R/?group_id=1025
It contains a workaround specifically to deal with gTables (and therefore ggplot2 graphics).
So to try and get your example to work, start up a new R session and run the following code:
install.packages("gridSVG", repos="http://R-Forge.R-project.org")
library(gridSVG)
library(ggplot2)
(p <- ggplot(mtcars, aes(wt, mpg)) + geom_point() + labs(title="link"))
titleGrobName <- grep("title", grid.ls(print=FALSE)$name, value=TRUE)
grid.hyperlink(titleGrobName, "http://www.r-project.org/")
gridToSVG("HyperlinkExample.svg", "none", "none")
The only real difference here are the additional parameters given to gridToSVG(). This is mainly to reduce the output to just the SVG file and an HTML wrapper (otherwise you also get some JSON data, which is not useful for your example).
As far as getting the correct mainGrobName this code would succeed (and not create the distracting side-effects by setting print=FALSE):
grep("title", grid.ls(print=FALSE)$name, value=TRUE)
#[1] "title.2-4-2-4"
The structure of the plot object is clearly more complex than in the lattice situation and the gridToSVG does not capture it by default:
grep("title", grid.ls()$name, value=TRUE)
#--------------------
GRID.gTableParent.125
background.1-5-6-1
spacer.4-3-4-3
panel.3-4-3-4
grill.gTree.103
panel.background.rect.94
panel.grid.minor.y.polyline.96
panel.grid.minor.x.polyline.98
panel.grid.major.y.polyline.100
panel.grid.major.x.polyline.102
geom_point.points.90
panel.border.zeroGrob.91
axis-l.3-3-3-3
axis.line.y.zeroGrob.113
axis
axis-b.4-4-4-4
axis.line.x.zeroGrob.107
axis
xlab.5-4-5-4
ylab.3-2-3-2
title.2-4-2-4
This is also interesting output but I fail to see how I can get gridToSVG to convert it into a useful HTML object:
grid.ls( print=pathListing )$name

Resources