Save DiagrammeR object to PNG on disc - r

I am using the lavaanPlot-Package to plot my Path Model created with lavaan. Works like a charm. Just to make it easier here is a reproducible example
Reproducible Example
library(pacman)
p_unload()
p_load(dplyr,lavaan,webshot,lavaanPlot)
model <- 'mpg ~ cyl + disp + hp
qsec ~ disp + hp + wt'
fit <- sem(model, data = mtcars)
summary(fit)
plot <- lavaanPlot(model = fit,
node_options = list(shape = "box", fontname = "Helvetica"),
edge_options = list(color = "grey"),
coefs = F)
plot
However I would like to save the result to a png file on my disc (rather than utilizing some
form of screenshot). Digging in the docs I found out that lavaanPlot returns a Diagrammer Object.
I tried to get a png file with three different approaches
Approaches
1. Webshot
Gives me the error webshot.js returned failure value: 1
2. export_graph
I found some suggestion how to fix it this link on SO, suggesting to use DiagrammeR export_graph. However this gives me the following error:
Fehler: `export_graph()` REASON:
* The graph object is not valid
3. export_svg
Additionally I found this suggested solution on github, which I couldnt get to work either. It produces a SVG file for me which I cant open properly
# Try 1 using webshot
webshot("Plot_test_webshot.png")
# Try 2 export_graph
plot %>%
export_graph(file_name = "pic.png",
file_type = "png")
export_graph(plot,
file_name = "pic.png",
file_type = "png")
# Try 3 export_svg
plot %>%
export_svg() %>%
charToRaw %>%
rsvg_pdf("./path_to_svg_file.svg")

I was able to find a solution in the Github of the maintainer of the package.
Posting this in the hope that anyone in the future looking for a solution will find this
# Export Function for lavaanPlot Obtained from github
# https://github.com/alishinski/lavaanPlot/blob/export_plots/R/plotExportFunctions.R
save_png <- function(plot, path){
DiagrammeRsvg::export_svg(plot) %>%
charToRaw() %>%
rsvg::rsvg() %>%
png::writePNG(path)
}
Also on Github there is a branch in which this functionality is already included.

Related

webshot2::webshot is trimming the right side off of a huxtable in R

I am trying to convert an html table created in R via the huxtable package to a png file using webshot2::webshot. Unfortunately, the very right side of the output seems to get trimmed off and I can't figure out how to fix this generically.
I don't want to manually tweak the cliprect parameter because I'll need to do this for many tables and its not scalable if its not generic. However, it is possible to achieve it with this parameter so I wonder why its failing with the other workflow.
Here's an example illustrating the problem:
library(magrittr)
library(huxtable)
set.seed(1337)
data <- matrix(rnorm(25), 35, 10)
my_hux <- as_hux(data) %>%
set_outer_borders(0.4) %>%
map_background_color(by_rows("grey95", "white")) %>%
map_text_color(by_quantiles(c(0.1, 0.9), c("red", "black", "green3")))
quick_html(my_hux, file = "ahuxtable.html", open = FALSE)
webshot2::webshot(url = "ahuxtable.html", file = "ahuxtable.png",
zoom = 5, selector = "table")
I tried this with webshot::webshot, however the webshot package seems to be webshot2's predecessor so I'd prefer a webshot2 solution if there is one.

Profiling in RStudio - profvis() not giving desired outputs

I am trying to learn how to profile in R, and am in need of some help. I am using the profvis() function, and am following the examples both in Chapter 7 of Colin Gillespie's Efficient R programming, and the Rstudio support page for profiling: https://support.rstudio.com/hc/en-us/articles/218221837-Profiling-with-RStudio.
However, when I run the same code as their examples, I am not getting the same outputs. For example:
library("profvis")
profvis({
data(movies, package = "ggplot2movies") # Load data
movies = movies[movies$Comedy == 1,]
plot(movies$year, movies$rating)
model = loess(rating ~ year, data = movies) # loess regression line
j = order(movies$year)
lines(movies$year[j], model$fitted[j]) # Add line to the plot
})
I should be getting an output like this:
Efficient R Output
but instead I am getting an output like this:
My output
In fact, this output isn't always consistent (for example, sometimes sources not available), but always has the "profvis" as the bottom of the flame graph, which is not the case with any examples I've seen.
I have a similar problem when running the example from the RStudio support page:
library(profvis)
profvis({
data(diamonds, package = "ggplot2")
plot(price ~ carat, data = diamonds)
m <- lm(price ~ carat, data = diamonds)
abline(m, col = "red")
})
Support Page Output
But after running the code three times in a row, here are my 3 outputs, all with the profvis in the flame graph:
Output_1
Output_2
Output_3
Also, one last note: I have fully updated R and RStudio and this did not help.
I am very confused as to why this is happening, and can't find any examples of this online. I hope I'm not missing anything obvious, and would greatly appreciate any help.
Thanks.

How to create tables in R

I am trying to create and export a table for publication (picture attached).
I have created a table using the code below, but I could not export it as a table.
Can anyone help, please
library(tidyverse)
library(gapminder)
data(gapminder)
median_gdp <- median(gapminder$gdpPercap)
gapminder %>%
select(-country) %>%
mutate(gdpPercap = ifelse(gdpPercap > median_gdp, "high", "low")) %>%
mutate(gdpPercap = factor(gdpPercap)) %>%
mutate(pop = pop / 1000000) -> gapminder
gapminder <- lapply(gapminder, function(x) x[sample(c(TRUE, NA),
prob = c(0.9, 0.1),
size = length(x),
replace = TRUE
)])
library(arsenal)
table_one <- tableby(continent ~ ., data = gapminder)
summary(table_one, title = "Gapminder Data", text=TRUE)
If you want to write a table to Microsoft Word, you can use the following code from arsenal package.
write2word(table_one, "table.doc",
keep.md = TRUE,
quiet = TRUE,
title = "Your title")
You can also write a table to pdf and HTML by using the arsenal package. For the details, see
?write2specific
Weirdly, there doesn't seem to be a general question on this topic, though see Create a PDF table for PDFs.
Modern packages to print tables in output formats, including PDF, HTML and Word, include gt, huxtable, flextable and kableExtra.
Packages to create tables of summary statistics include skimr, summarytools and qwraps2. Some of these also have built-in output to different formats.
There are many other packages out there.

ggSave group_by df list of ggarrange'd ggplot objects

I've used group_by, do, and ggplot - twice - to create two simple dfs of Date (the group) and a list of the ggplot outputs, thanks hugely to help from examples on this site. Simplified example:
p1 <- df_i %>% group_by(Date) %>% do(
plots = ggplot(data = .) +
geom_line() #etc, hugely long and detailed ggplot call omitted for brevity, but it works fine
) # close do
I can then join those dfs,
p1 <- cbind(p1, p2[,2])
names(p1) <- c("Date", "Temp", "Light") #Temp & Light were both "plots" from above
And loop through the rows, saving the outputs in a 1-row (top & bottom object) ggarranged png:
for (j in 1:nrow(p1)) {
ggsave(file = paste0(p1$Date[j], ".png"),
plot = arrangeGrob(p1$Temp[[j]], p1$Light[[j]]),
device="png",scale=1.75,width=6.32,height=4,units="in",dpi=300,limitsize=TRUE)
}
So far, so good. But nature abhors a for-loop, so I was trying to do the ggsaving in a group_by, using the same ggsave parameter options, changing only what's needed given the difference in for-loop indexing vs (what I understand of) group_by subsetting:
p1 %>% group_by(Date) %>%
ggsave(file = paste0(.$Date, ".png"),
plot = arrangeGrob(Temp, Light),...) #other params hidden here for brevity
Error in grDevices::png(..., res = dpi, units = "in"): invalid
'pointsize' argument
If I add pointsize=10 it says "invalid bg value"; add bg = "white":
Error in check.options(new, name.opt = ".X11.Options", envir =
.X11env) : invalid arguments in 'grDevices::png(..., res = dpi,
units = "in")' (need named args)
(I also tried lowering dpi to no effect). Possibly I'm going about this the wrong way, e.g. swapping %>% for %$% in Vlad's suggestion from magrittr:
Error in gList(list(list(data = list(DateTimeUTCmin5 = c(915213660, 915213780, :
only 'grobs' allowed in "gList"
This gives the same error with Date and .$Date in the ggsave call. Trying to recreate the do framework:
p1 %>% group_by(Date) %>%
do(ggsave(file = paste0(.$Date, ".png"),"_", .$Date, ".png"),
plot = arrangeGrob(Temp, Light), #etc
Error in arrangeGrob(Temp, Light) : object 'Temp' not found
p1 %>% group_by(Date) %>%
do(ggsave(file = paste0(.$Date, ".png"),"_", .$Date, ".png"),
plot = arrangeGrob(.$Temp, .$Light), #etc
Error in gList(list(list(data = list(DateTimeUTCmin5 = c(915213660,
915213780, : only 'grobs' allowed in "gList"
Which gives the same error if I use %$%.
Does anyone have the connected stack of understanding of these tools such that they can see what I'm doing wrong here? It seems like I should be close, but I'm increasingly groping around in the dark. Any pointers very much appreciated. Thanks in advance!
Equally if folks recommend a different approach I'm interested too. It strikes me that I could use an lapply (or parSapply) instead of the for-loop on the p1 df. Do operations on grouped dfs outperform apply operations?
[Edit: desired final output: ggsave dumps 1 image (with 2 plots on it) per Date, into the specified folder. Essentially if I can get ggsave to work within the grouped_df, that should be that]

Prevent plot.gam from producing a figure

Say, I have a GAM that looks like this:
# Load library
library(mgcv)
# Load data
data(mtcars)
# Model for mpg
mpg.gam <- gam(mpg ~ s(hp) + s(wt), data = mtcars)
Now, I'd like to plot the GAM using ggplot2. So, I use plot.gam to produce all the information I need, like this:
foo <- plot(mpg.gam)
This also generates an unwanted figure. (Yes, I realise that I'm complaining that a plotting function plots something...) When using visreg in the same way, I'd simply specify plot = FALSE to suppress the figure, but plot.gam doesn't seem to have this option. My first thought was perhaps invisible would do the job (e.g., invisible(foo <- plot(mpg.gam))), but that didn't seem to work. Is there an easy way of doing this without outputting the unwanted figure to file?
Okay, so I finally figured it out 5 minutes after posting this. There is an option to select which term to plot (e.g., select = 1 is the first term, select = 2 is the second), although the default behaviour is to plot all terms. If, however, I use select = 0 it doesn't plot anything and doesn't give an error, yet returns exactly the same information. Check it out:
# Load library
library(mgcv)
# Load data
data(mtcars)
# Model for mpg
mpg.gam <- gam(mpg ~ s(hp) + s(wt), data = mtcars)
# Produces figures for all terms
foo1 <- plot(mpg.gam)
# Doesn't produce figures
foo2 <- plot(mpg.gam, select = 0)
# Compare objects
identical(foo1, foo2)
[1] TRUE
Bonza!

Resources