problem with svg device, expression(), and unicode characters - r

I am having difficulty using the svg device with math expressions and unicode (in this case, left- and right-quotes). This only occurs on my Windows 10 computer; my osx computer seems unaffected. Consider the following R code:
output = tempfile(fileext = ".svg")
svg(file = output)
plot(1, axes=FALSE, ty='n')
## Line A:
mtext(side = 2, text = expression(paste("A")))
## Line B:
mtext(side = 3, text = expression(paste("“B")))
## Line C:
mtext(side = 4, text = expression(paste("C")))
axis(1, at = par()$usr[1:2], lab = c("More", "Less"), tick = FALSE)
dev.off()
## Uncomment and run to open the SVG file to look at it
# browseURL(output)
(Note the left-quote in Line B). Upon running Line C, I get
Error in mtext(side = 4, text = expression(paste("C"))) :
metric information not available for this device
If I change the device to png I get the output I expect.
If I comment out lines B and C, I get the output I expect (eg, the output from lines A and the axis)
If I comment out only line C, I do not get the output I expect. Neither line B works, nor the axis. There appears to be something wrong with line B that causes everything later in the chunk to fail too.
If I remove the expression() from line B, everything works as expected (including the unicode left-quote)
If I change the font using showtext (see the issue for details: https://github.com/yihui/knitr/issues/1831) I have no problem.
This appears, then, to be an interaction between svg, expression, the default font, and unicode. But only on Windows 10. My OSX computer (see details below) does not have the issue.
sessionInfo()
R version 3.6.2 (2019-12-12)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] reprex_0.3.0
loaded via a namespace (and not attached):
[1] Rcpp_1.0.4.6 ps_1.3.2 digest_0.6.25 R6_2.4.1 evaluate_0.14 rlang_0.4.5 fs_1.4.1
[8] callr_3.4.3 whisker_0.4 rmarkdown_2.1 Cairo_1.5-12 tools_3.6.2 xfun_0.13 compiler_3.6.2
[15] processx_3.4.2 clipr_0.7.0 htmltools_0.4.0 knitr_1.28.3
OSX session info (no problem on this computer)
> xfun::session_info('knitr')
R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Catalina 10.15.4, RStudio 1.2.5031
Locale: en_GB.UTF-8 / en_GB.UTF-8 / en_GB.UTF-8 / C / en_GB.UTF-8 / en_GB.UTF-8
Package version:
evaluate_0.14 glue_1.4.0 graphics_3.6.1 grDevices_3.6.1
highr_0.8 knitr_1.28.3 magrittr_1.5 markdown_1.1
methods_3.6.1 mime_0.9 stats_3.6.1 stringi_1.4.6
stringr_1.4.0 tools_3.6.1 utils_3.6.1 xfun_0.12
yaml_2.2.1
Any idea what is causing this?

I get the same problem on my 32-bit Windows work PC. It's a tricky error to track down, but I eventually found it is being thrown here in the GMMathText function of graphics.c. As you describe, it only seems to be a problem with expressions containing certain characters on some graphics devices. In particular, anything using Cairo on Windows seems to stub its toe at the same point.
After attempting several hacks to get around this, I found that the best solution is to simply use bquote instead of expression. This allows you to keep all of the plotmath functionality you get with expression without generating the error:
svg(output)
plot(1, axes=FALSE, ty='n')
mtext(side = 2, text = bquote("A"))
mtext(side = 3, text = bquote("“B"))
mtext(side = 4, text = bquote("C"))
axis(1, at = par()$usr[1:2], lab = c("More", "Less"), tick = FALSE)
dev.off()
Which gives the following SVG:
There is a nice overview of how to use bquote to generate your labels, including all the maths expressions you need here

I'm taking something of a guess here because I know nothing about R. However the local for your windows box is cp1252 which does not contain Unicode quotes but uses Microsoft's smart quotes.
You say it works in OS-X which looking at your session info is set up to use UTF-8.
I'm assuming that your program file is saved as UTF-8.

Related

RStudio makes my graphs turn grey when I expand them

I'm using a script in RStudio which produces several graphs. This is a (very simplified) example of how it looks
mpg = mtcars$mpg
cyl = mtcars$disp
hp = mtcars $hp
plot(mpg, cyl)
dev.new()
plot(mpg,hp)
dev.new()
plot(hp, cyl)
When I run this in RStudio (using the "Source" key), the first graph stays in the "Plots" viewer in the lower right of the Rstudio window (I would actually like it to be a separate window as well if anyone knows how to do that), and the second and third graphs are produced as individual windows separate from the RStudio screen.
When I try to change the size of these windows (by pressing the full screen button in the top right corner, or by dragging the side), the most recently generated window is fine and resizes, but the previous one turns grey and the graph stops showing.
I thought it might have something to do with the fact that the graphics devices are inactive, but the most recently generated one, which rescales fine, also says it's inactive.
Any help would be appreciated! Thanks.
Edit: here is the output of sessionInfo():
> sessionInfo()
R version 4.0.0 (2020-04-24)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] DescTools_0.99.36 dplR_1.7.1
loaded via a namespace (and not attached):
[1] Rcpp_1.0.4.6 mvtnorm_1.1-1 lattice_0.20-41 matrixStats_0.56.0 XML_3.99-0.3 png_0.1-7
[7] digest_0.6.25 MASS_7.3-51.5 R.methodsS3_1.8.0 grid_4.0.0 plyr_1.8.6 signal_0.7-6
[13] magrittr_1.5 stringi_1.4.6 rstudioapi_0.11 R.oo_1.23.0 R.utils_2.9.2 Matrix_1.2-18
[19] boot_1.3-24 tools_4.0.0 stringr_1.4.0 compiler_4.0.0 expm_0.999-4
It's not a perfect answer, but here's what I found to work around it:
When you generate a number of graphics devices the most recently generated one remains "active" while the rest are inactive. If you don't close the active window and resize the others, it works fine. But if you close the active window and then try to resize the others, they just go grey. Somehow, closing the active window shuts down something and stops you from being able to resize the graphs at all. Weird.

Saving plots as EMF files

I am having an issue with the emf() function from the devEMF package.
The code I am using -
library(devEMF)
emf(file = "trial.emf")
plot(1:10, seq(10, 100, 10), type = "l", xlab = "Time", ylab = "Distance")
#sample plot
dev.off()
This does not have the plot line but does have everything else (labels, axis ticks, title).
Am I missing some graphics package?
sessionInfo()
#R version 3.3.2 (2016-10-31)
#Platform: x86_64-w64-mingw32/x64 (64-bit)
#Running under: Windows 7 x64 (build 7601) Service Pack 1
#locale:
#[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United #
#States.1252
#[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C
#[5] LC_TIME=English_United States.1252
#attached base packages:
#[1] stats graphics grDevices utils datasets methods base
#other attached packages:
#[1] devEMF_3.6
#loaded via a namespace (and not attached):
#[1] tools_3.3.2
Some of the defaults in that function are not ideal if you are trying to view outside of LibreOffice.
try this:
library(devEMF)
emf(file = "trial.emf", emfPlus = FALSE)
plot(1:10, seq(10, 100, 10), type = "l", xlab = "Time", ylab = "Distance")
dev.off()
Make sure that emfPlus = FALSE. If you view the plot generated by emfPlus = TRUE in LibreOffice you will see it looks fine. Use emfPlus = FALSE when working with other viewers.
Most likely the program being used to view the resulting emf graphic does not support EMF+ records.
As alluded in JMT2080AD's answer, the devEMF library can produce either "EMF" or "EMF+" files. The newer EMF+ format (https://msdn.microsoft.com/en-us/library/cc230724.aspx) has been around since 2007 and is supported by more recent closed-source programs (i.e., Office 2010) but support is missing from old programs (e.g., older versions of Adobe Illustrator) and spotty in many open-source programs (e.g., LibreOffice, Inkscape).
For better or for worse, EMF+ records are embedded within EMF comment records, which means older programs will silently ignore them.
I find that the devEMF defaults produce acceptable files for Microsoft Office 2010 and LibreOffice >5.1.6. While LibreOffice support for EMF+ is incomplete, the unsupported features are turned off by default in the call to emf(). That said, JMT2080AD's suggestion of setting emfPlus = FALSE in the call to emf() is likely to make the files viewable by more programs (at the cost of losing features such as transparency and anti-aliasing).
(Disclosure: I am the author of the devEMF package)

Make R Studio plots only show up in new window

When using R Studio, I usually just work with an .R file stacked on top of the Console. I keep the other panes (Environment, History, Files, etc) hidden.
But whenever I plot a graph, the other panes automatically pop out of the side bar to show me the Plot pane. Because I work on a laptop, this makes everything too small to see. By clicking the Zoom button on the Plots pane, I can get the plot also show up in a new window, but does not prevent the Plots pane from showing up.
Is there a way to "disable" the Plots pane in R Studio, and force plots show up in a new window?
> sessionInfo()
R version 3.2.3 (2015-12-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils
[5] datasets methods base
other attached packages:
[1] ggplot2_2.2.1 jsonlite_1.4
[3] data.table_1.10.4
loaded via a namespace (and not attached):
[1] labeling_0.3 colorspace_1.2-6
[3] scales_0.4.1 lazyeval_0.2.0
[5] plyr_1.8.4 tools_3.2.3
[7] gtable_0.1.2 tibble_1.3.0
[9] curl_2.5 Rcpp_0.12.10
[11] grid_3.2.3 munsell_0.4.2
>
The dev.new() function will open a new plot window, which then becomes the target for all plots.
If you wish to open another window you can run the command a second time to open a second window.
dev.off() will shut down the window (in the order they were opened by default).
You can see how to control multiple graphics devices in the documentation here.
In RStudio, the default graphics device is normally "RStudioGD". You can change that to something else: the normal choices are "windows" on Windows, "quartz" on MacOS, "X11" on Linux. So for example, use
options(device = "quartz")
in your RStudio session on a Mac and you'll get the regular MacOS graphics window.
Try using the windows command before your plot call.
windows();(mpg ~ wt, mtcars)
The plot should pop-up in its own window whilst the pane stays minimized.
Commenting the following lines in C:\Program Files\RStudio\R\Tools.R seems to work (it may be necessary to edit the file as administrator):
# set our graphics device as the default and cause it to be created/set
.rs.addFunction( "initGraphicsDevice", function()
{
# options(device="RStudioGD")
# grDevices::deviceIsInteractive("RStudioGD")
grDevices::deviceIsInteractive()
})
If you want all plots in the current script to appear on a separate window, this should do the job:
dev.new(noRStudioGD = TRUE)
*Tested on RStudio version 1.4.1106 for Windows with R version 4.0.5 (2021-03-31)
For a 'permanent' solution, the answer by Rubén Fernández-Casal should work well.
You can force RStudio to show plots in the Source window if you use R Markdown. In a Rmd file, plots are shown together with code; it's called an R Markdown notebook. You can set the size of the plots too, in what is called an R code chunk:
```{r fig.height = 2, fig.width = 3}
plot(mpg ~ wt, mtcars)
```
When you run the chunk, the plot is shown below it.
If you want to set the plot size for the whole notebook, set the package option using opts_knit and opts_chunk, for example:
```{r setup}
library(knitr)
opts_knit$set(global.par = TRUE)
opts_chunk$set(fig.width = 4.5, fig.height = 3.5)
```
For more information, see here and here.

Scaling of plot in ggsave() different when RStudio plot pane is active

I cannot provide a reproducible example for this, but I wanted to ask about a curious behavior of the ggsave() function: I am experiencing the following:
I create a ggplot, by assigning a plot to a variable, let's say p
I evaluate p and - as it should be - the plot is displayed in the plot pane of RStudio.
My next call is ggsave(plot = p, filename = "plot.pdf"), the plot is
written to plot.pdf and R gives me the dimensions of the written plot on the console.
The strange thing is: When the RStudio plot pane is active (i.e. a RStudio graphics device is open), the dimensions of the plot written by ggsave() in step 3 are different than when no RStudio graphics device is open. Consequently, the scalings of the written plot are off. In other words: Step 3 produces different results depending on the execution of step 2. Does anyone know why this is the case? I thought that ggsave() is totally independent of any RStudio device. Or does this only happen on my machine?
This is my sessionInfo():
R version 3.4.1 (2017-06-30)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Sierra 10.12.6
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib
locale:
[1] de_DE.UTF-8/de_DE.UTF-8/de_DE.UTF-8/C/de_DE.UTF-8/de_DE.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] ggplot2_2.2.1 scales_0.4.1 data.table_1.10.4
loaded via a namespace (and not attached):
[1] ggrepel_0.6.12 Rcpp_0.12.12 digest_0.6.12 grid_3.4.1 plyr_1.8.4 gtable_0.2.0 rlang_0.1.2 lazyeval_0.2.0
[9] labeling_0.3 RColorBrewer_1.1-2 tools_3.4.1 munsell_0.4.3 compiler_3.4.1 colorspace_1.3-2 sciplot_1.1-1 tibble_1.3.3
Expanding on Andrey Kolyadin's comment above...
From ggsave() documentation 'width, height Plot size in units ("in",
"cm", or "mm"). If not supplied, uses the size of current graphics
device.'
If we dig into the code behind ggsave, there's a snippet that says:
if (any(is.na(dim))) {
if (length(grDevices::dev.list()) == 0) {
default_dim <- c(7, 7)
}
else {
default_dim <- grDevices::dev.size() * scale
}
...
Which means that if the dimensions are not specified by the user:
if there's no active graphics device at all, default dimensions are 7 x 7;
if there's at least one active graphics device, use the dimensions of the last one (multiplied by scale, which defaults to 1).
RStudio's plot pane is a graphics device. So ggsave's behaviour differs depending on whether there's anything there.

knitr, RGL and legend3d: legend3d didn't show up in the html generated by knitr

I am able to create a dynamic 3D scatter plot using rgl and knitr, but the legend created by the legend3d is missing. I guess it may be related to the implementation of hook_webgl. Any idea? Thank you.
Here are the code I used to create the 3D scatter plot:
```{r fig1, webgl=TRUE, fig.width=10 , fig.height = 10}
library(knitr)
library(rgl)
knit_hooks$set(webgl = hook_webgl)
x <- sort(rnorm(1000))
y <- rnorm(1000)
z <- rnorm(1000) + atan2(x,y)
plot3d(x, y, z, col=rep(1:2,each=500))
legend3d("topright",legend=c("Type 1","Type 2"), pch=16, col=1:2)
```
My session info:
R version 3.1.3 (2015-03-09)
Platform: i386-w64-mingw32/i386 (32-bit)
Running under: Windows Server 2008 R2 x64 (build 7601) Service Pack 1
locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods
[7] base
other attached packages:
[1] knitr_1.11 rgl_0.95.1441 dplyr_0.4.3
loaded via a namespace (and not attached):
[1] assertthat_0.1 DBI_0.3.1 digest_0.6.8 evaluate_0.8
[5] formatR_1.2.1 highr_0.5.1 htmltools_0.3 lazyeval_0.1.10
[9] magrittr_1.5 parallel_3.1.3 R6_2.1.2 Rcpp_0.12.3
[13] rmarkdown_0.9.5 stringi_0.5-5 stringr_1.0.0 tools_3.1.3
[17] yaml_2.1.13
Looks like a bug in the rglwidget code; I'll look into it.
I recommend a few changes to your programming style. These won't help with this bug, but may save you problems later:
Use the setupKnitr() function rather than setting the knitr hook yourself. The link to knitr is likely to change, but setupKnitr() will protect you from problems.
Rather than saying webgl=TRUE in the chunk options, make a call to the rglwidget::rglwidget() function when you want to draw the plot. I'm hoping to make this call unnecessary in the future (more like what happens with regular plots), but for now it's the better tested way to do things.
Update your R. Current version is 3.2.3, with 3.2.4 due quite soon.
Use rgl and rglwidget from R-forge. They are newer than the CRAN versions, and have several bug fixes. Hopefully soon they'll have the legend bug fix too.
Added later:
This wasn't so much a bug as something that wasn't implemented. Now it is, if you use rgl version 0.95.1456 and rglwidget version 0.1.1456, both available from R-forge. Not much testing yet, so there may be more changes over the next while.

Resources