Chunk option eval=FALSE ignored when spinning R-script - r

Spinning the following code (by clicking compile report in Rstudio):
#+ eval = FALSE
This line should not be syntax-checked, but it is.
Returns this error:
Error in parse(text = x, keep.source = TRUE) :
<text>:2:6: unexpected symbol
1: #+ eval = FALSE
2: This line
Knitting the equivalent Rmd-chunk works fine:
```{r, eval = FALSE}
Using Rmd, eval=FALSE disables the syntax-check, and does not error
I was expecting that I could spin a chunk syntactically incorrect code without getting an error (https://bookdown.org/yihui/rmarkdown-cookbook/spin.html). Am I mistaken for expecting this?
Thanks.

This is not possible, but a workaround is to quote the sentence :
# Syntax checked:
2+2
#> [1] 4
# Not syntax checked:
"
2 a
"
#> [1] "\n2 a \n"
(source: Yihui Xie's comment above at 28jun2022)

Related

Error in -title : invalid argument to unary operator Execution halted

I used CronJobs to schedule my R markdown to run everyday at 6pm. However, it did not run the script and gave me the following error:Error in -title : invalid argument to unary operator
Execution halted.
The work directory is set to my source location.
Any advice? Thanks!
Here is my code:
---
title: "EXAMPLECODE"
author: "XXXX"
date: "5/4/2020"
output: pdf_document
---
#STEP 1: INSTALL AND LOAD RCURL PACKAGE
```{r}
install.packages("RCurl")
library(RCurl)
```
#STEP 2: READ IN CSV FILE FOR EXAMPLE
```{r}
Example<- getURL("https://www.EXAMPLEURLHERE.csv")
ExampleData <- read.csv(text = Example)
ExampleData
```
#STEP 3: SAVE DATA INTO CSV FILE
```{r}
write.table(ExampleData, file="ExampleData_Update.csv", sep=",")
```
This error is common when you have a unary operator (e.g., -, +, or !) that is out of place. This indicates you have a typo or an object that is empty or not what you think. A guess (since you haven't responded to #AllanCameron's understated suggestion) is that you have a variable named title somewhere, assume that it is numeric or something you can index a vector/list/frame off of, and it is either non-numeric or empty. I can reproduce this precise error with
title <- c()
mtcars[-title,]
# Error in -title : invalid argument to unary operator
title <- "1"
mtcars[-title,]
# Error in -title : invalid argument to unary operator
If you want a stack-trace on errors, then you might take a suggestion from https://renkun.me/2020/03/31/a-simple-way-to-show-stack-trace-on-error-in-r/:
options(error = function() {
sink(stderr())
on.exit(sink(NULL))
traceback(3, max.lines = 1L)
if (!interactive()) {
q(status = 1)
}
})
mtcars[-title,]
# Error in -title : invalid argument to unary operator
# 2: `[.data.frame`(mtcars, -title, )
# 1: mtcars[-title, ]
In which case it tells you a little more. If it's in a function, that stack trace gives you the line number.
myfunc <- function(title) {
1+1 # doing something
2*2 # doing something else
3^3 # yawn
mtcars[-title,]
}
myfunc(1:30)
# mpg cyl disp hp drat wt qsec vs am gear carb
# Maserati Bora 15.0 8 301 335 3.54 3.57 14.6 0 1 5 8
# Volvo 142E 21.4 4 121 109 4.11 2.78 18.6 1 1 4 2
myfunc(c())
# Error in -title : invalid argument to unary operator
# 3: `[.data.frame`(mtcars, -title, ) at #5
# 2: mtcars[-title, ] at #5
# 1: myfunc(c())
(I know, title is mis-named here, just over-proving the point.)
(Just to assert again: I demonstrated on a data.frame, but this works with vectors/lists as well: (1:10)[-title])
Further, upon seeing your "script": it is not a script. It is a document. If I'm correct, then you are calling this something like Rscript /path/to/file.Rmd. In that case, R thinks this is an R script file, not an R-markdown file.
Let's try this on the console. Copy the following (newline and all) and paste it into your R console:
---
title: "EXAMPLECODE"
When you see the "unary" error, you'll realize that R is interpreting this as a command. In a literal sense, R sees this as: "negate negate negate (newline/whitespace ignored) symbol(title) sequence-colon string(EXAMPLECODE)". (In)Conveniently, title is also a base function in R, so it exists; if it were instead
---
mytitle: "EXAMPLECODE"
(which is not valid Rmd), then your error would have instead read
Error: object 'mytitle' not found
which would have been slightly more clear/informative.
So ultimately I don't know for sure, but my guess is that you are inadvertently telling R to try to interpret the whole thing as an R script, which it is not. Perhaps Rscript knitr::knit("/path/to/file.Rmd") or similar will work instead.
In case someone else gets here, I scratched my head over this error for a ridiculously long time before I realized that I'd coded all the assignment operators in the script as '<--'. I guess I got confused by some software's use of that as a shortcut to an arrow.
Should be -- obvious, I know, but I just have to say it: '<-'

r - source script file that contains unicode (Farsi) character

write the text below in a buffer and save it as a .r script:
letters_fa <- c('الف','ب','پ','ت','ث','ج','چ','ح','خ','ر','ز','د')
then try these lines to source() it:
script <- "path/to/script.R"
file(script,
encoding = "UTF-8") %>%
readLines() # works fine
file(script,
encoding = "UTF-8") %>%
source() # works fine
source(script) # the Farsi letters in the environment are misrepresented
source(script,
encoding = "UTF-8") # gives error
The last line throws error. I tried to debug it and I believe there is a bug in the source function, in the following lines:
...
loc <- utils::localeToCharset()[1L]
...
The error occurs at .Internal(parse( line.
...
exprs <- if (!from_file) {
if (length(lines))
.Internal(parse(stdin(), n = -1, lines, "?",
srcfile, encoding))
else expression()
}
else .Internal(parse(file, n = -1, NULL, "?", srcfile,
encoding))
...
The exact error is:
Error in source(script, encoding = "UTF-8") :
script.R:2:17: unexpected INCOMPLETE_STRING
1: #' #export
2: letters_fa <- c('
^
The solution to this problem is to either change the OS Locale to a native Locale (e.g. Persian in this case) or use R built-in function Sys.setlocale(locale="Persian") to change an R session native Locale.
Use source without specifying the encoding, and then modify the vector's encoding with Encoding:
source(script)
letters_fa
# [1] "الÙ\u0081" "ب" "Ù¾" "ت" "Ø«"
# [6] "ج" "چ" "ح" "خ" "ر"
# [11] "ز" "د"
Encoding(letters_fa) <- "UTF-8"
letters_fa
# [1] "الف" "ب" "پ" "ت" "ث" "ج" "چ" "ح" "خ" "ر" "ز" "د"

Log all warnings with futile.logger

Trying to log all errors and warnings with futile.logger.
Somewhat satisfied with this for dealing with errors:
library(futile.logger)
options(error = function() { flog.error(geterrmessage()) ; traceback() ; stop() })
log("a")
# Error in log("a") : argument non numérique pour une fonction mathématique
# ERROR [2016-12-01 21:12:07] Error in log("a") : argument non numérique pour une fonction mathématique
#
# No traceback available
# Erreur pendant l'emballage (wrapup) :
There is redundancy, but I can easily separate between stderr, stdout and log file, so it's not a problem. It's certainly not pretty, there is an additional "wrapup" error message somehow caused by the final stop() that I don't understand, so I'm open to suggestions.
I cannot find a similar solution for warnings. What I tried:
options(warn = 1L)
options(warning.expression = expression(flog.warn(last.warning)))
log(- 1)
# [1] NaN
But to no avail.
Follow-up question: Are there best practices that I am unknowingly ignoring?
How about:
options(warning.expression =
quote({
if(exists("last.warning",baseenv()) && !is.null(last.warning)){
txt = paste0(names(last.warning),collapse=" ")
try(suppressWarnings(flog.warn(txt)))
cat("Warning message:\n",txt,'\n',sep = "")
}
}))
In can contribute two options to log R conditions like warnings with futile.logger and catch all warnings no matter how deep the function call stack is:
Wrap your code with withCallingHandlers for a basic solution
Use my package tryCatchLog for an advanced solution (for compliance reason: I am the author)
To explain the solutions I have created a simple R script that produces warnings and errors:
# Store this using the file name "your_code_file.R"
# This could be your code...
f1 <- function(value) {
print("f1() called")
f2(value) # call another function to show what happens
print("f1() returns")
}
f2 <- function(value) {
print("f2() called")
a <- log(-1) # This throws a warning: "NaNs produced"
print(paste("log(-1) =", a))
b <- log(value) # This throws an error if you pass a string as value
print("f2() returns")
}
f1(1) # produces a warning
f1("not a number") # produces a warning and an error
Executed "as is" (without logging) this code produces this output:
[1] "f1() called"
[1] "f2() called"
[1] "log(-1) = NaN"
[1] "f2() returns"
[1] "f1() returns"
[1] "f1() called"
[1] "f2() called"
[1] "log(-1) = NaN"
Error in log(value) : non-numeric argument to mathematical function
Calls: source -> withVisible -> eval -> eval -> f1 -> f2
In addition: Warning messages:
1: In log(-1) : NaNs produced
2: In log(-1) : NaNs produced
Solution 1 (withCallingHandlers)
Create a new R file that is called by R and sources your unchanged (!) original R script:
# Store this using the file name "logging_injector_withCallingHandlers.R"
# Main function to inject logging of warnings without changing your original source code
library(futile.logger)
flog.threshold(INFO)
# Injecting the logging of errors and warnings:
tryCatch(withCallingHandlers({
source("your_code_file.R") # call your unchanged code by sourcing it!
}, error = function(e) {
call.stack <- sys.calls() # "sys.calls" within "withCallingHandlers" is like a traceback!
log.message <- e$message
flog.error(log.message) # let's ignore the call.stack for now since it blows-up the output
}, warning = function(w) {
call.stack <- sys.calls() # "sys.calls" within "withCallingHandlers" is like a traceback!
log.message <- w$message
flog.warn(log.message) # let's ignore the call.stack for now since it blows-up the output
invokeRestart("muffleWarning") # avoid warnings to "bubble up" to being printed at the end by the R runtime
})
, error = function(e) {
flog.info("Logging injector: The called user code had errors...")
})
If you execute this wrapper code the R output is:
$ Rscript logging_injector_withCallingHandlers.R
NULL
[1] "f1() called"
[1] "f2() called"
WARN [2017-06-08 22:35:53] NaNs produced
[1] "log(-1) = NaN"
[1] "f2() returns"
[1] "f1() returns"
[1] "f1() called"
[1] "f2() called"
WARN [2017-06-08 22:35:53] NaNs produced
[1] "log(-1) = NaN"
ERROR [2017-06-08 22:35:53] non-numeric argument to mathematical function
INFO [2017-06-08 22:35:53] Logging injector: The called user code had errors...
As you can see
warnings are logged now
the call stack could be output too (I have disabled this to avoid flooding this answer)
References: https://stackoverflow.com/a/19446931/4468078
Solution 2 - package tryCatchLog (I am the author)
Solution 1 has some drawbacks, mainly:
The stack trace ("traceback") does not contain file names and line numbers
The stack trace is flooded with internal function calls you don't want to see (believe me or try it with your non-trival R scripts ;-)
Instead of copying&pasting the above code snippet again and again I have developed a package that encapsulates the above withCallingHandlers logic in a function and adds additional features like
logging of errors, warnings and messages
identifying the origin of errors and warnings by logging a stack trace with a reference to the source file name and line number
support post-mortem analysis after errors by creating a dump file with all variables of the global environment (workspace) and each function called (via dump.frames) - very helpful for batch jobs that you cannot debug on the server directly to reproduce the error!
To wrap the above R script file using tryCatchLog create a wrapper file
# Store this using the file name "logging_injector_tryCatchLog.R"
# Main function to inject logging of warnings without changing your original source code
# install.packages("devtools")
# library(devtools)
# install_github("aryoda/tryCatchLog")
library(tryCatchLog)
library(futile.logger)
flog.threshold(INFO)
tryCatchLog({
source("your_code_file.R") # call your unchanged code by sourcing it!
#, dump.errors.to.file = TRUE # Saves a dump of the workspace and the call stack named dump_<YYYYMMDD_HHMMSS>.rda
})
and execute it via Rscript to get this (shortened!) result:
# $ Rscript -e "options(keep.source = TRUE); source('logging_injector_tryCatchLog.R')" > log.txt
[1] "f1() called"
[1] "f2() called"
WARN [2017-06-08 23:13:31] NaNs produced
Compact call stack:
1 source("logging_injector_tryCatchLog.R")
2 logging_injector_tryCatchLog.R#12: tryCatchLog({
3 logging_injector_tryCatchLog.R#13: source("your_code_file.R")
4 your_code_file.R#18: f1(1)
5 your_code_file.R#6: f2(value)
6 your_code_file.R#12: .signalSimpleWarning("NaNs produced", quote(log(-1)))
Full call stack:
1 source("logging_injector_tryCatchLog.R")
2 withVisible(eval(ei, envir))
...
<a lot of logging output omitted here...>
As you can see clearly at the call stack level 6 the source code file name and line number (#12) is logged as the source of the warning together with the source code snippet throwing the warning:
6 your_code_file.R#12 .signalSimpleWarning("NaNs produced", quote(log(-1)))
The way you should use futile.logger is shown in its documentation. Here us a quick example, of how it typically is used, and how to set the threshold.
# set log file to write to
flog.appender (appender.file ("mylog.log"))
# set log threshold, this ensures only logs at or above this threshold are written.
flog.threshold(WARN)
flog.info("DOES NOT LOG")
flog.warn ("Logged!")

Error handling within Sexpr

How do I permit errors within \Sexpr?
I have a knitr document. A small part of this document refers to a file that cannot be shared. So whenever \Sexpr{a} is called on for some object a that depends on that file being read, it returns an error. I'd like instead for \Sexpr to print that it encountered an error.
For example,
\documentclass{article}
\usepackage{xcolor} % for red
\begin{document}
<<>>=
x <- 1
#
The value of $x$ is \Sexpr{x}
<<>>=
a <- scan("secret_file.txt")
#
The value of $a$ is \Sexpr{a}.
\end{document}
will not compile (when secret_file.txt isn't present). I'd like the output to look something like:
I thought that altering the inline hook would work, but putting the following chunk made no difference.
<<Sexpr-setup>>=
library(knitr)
knit_hooks$set(inline = function(x){
out <- tryCatch(
{
if (is.numeric(x))
x = round(x, getOption("digits"))
paste(as.character(x), collapse = ", ")
},
error = function(cond){
return("\\textcolor{red}{\\textbf{Sexpr error!}}")
invisible(NULL)
},
warning = function(cond){
return("\\textcolor{red}{\\textbf{Sexpr warning!}}")
invisible(NULL)
}
)
return(out)
})
#
It is not essential to have a custom error message, only that errors are clear from the output and do not prevent compilation. I appreciate that I could do a find replace into something like \Sexpr{XX( and define a function upfront XX() that does the same tryCatch maneouvre, but I thought knitr could do this.
Calling knitr::knit on the above and applying the traceback shows that:
11: eval(expr, envir, enclos)
10: eval(parse_only(code[i]), envir = envir)
9: withVisible(eval(parse_only(code[i]), envir = envir))
8: inline_exec(block)
7: in_dir(opts_knit$get("root.dir") %n% input_dir(), inline_exec(block))
6: call_inline(x)
5: process_group.inline(group)
4: process_group(group)
3: withCallingHandlers(if (tangle) process_tangle(group) else process_group(group),
error = function(e) {
setwd(wd)
cat(res, sep = "\n", file = output %n% "")
message("Quitting from lines ", paste(current_lines(i),
collapse = "-"), " (", knit_concord$get("infile"),
") ")
})
2: process_file(text, output)
1: knitr::knit("knitr-prevent-errors.Rnw", quiet = TRUE)
From following the functions, it appears that the error is low down at
eval(parse_only(code[i]), envir = envir)
Where code[i] is a. Am I right in thinking that the only way to resolve this is to change the line starting v = with a tryCatch?
With the option include=FALSE in the setup chunk,the following worked for me with output as below. If it does not work for you I will delete the post
\documentclass{article}
\usepackage{xcolor} % for red
<<setup, include=FALSE>>=
knit_hooks$set(inline = function(x) {
out <- tryCatch(
{
if (is.numeric(x))
x = round(x, getOption("digits"))
paste(as.character(x), collapse = ", ")
},
error = function(cond){
return("\\textcolor{red}{\\textbf{Sexpr error!}}")
invisible(NULL)
},
warning = function(cond){
return("\\textcolor{red}{\\textbf{Sexpr warning!}}")
invisible(NULL)
}
)
return(out)
})
#
\begin{document}
<<>>=
x <- 1
#
The value of $x$ is \Sexpr{x}
<<>>=
a <- scan("secret_file.txt")
#
The value of $a$ is \Sexpr{a}.
\end{document}
Knitr Output:
>knitr::knit("test.Rnw")
processing file: test.Rnw
|......... | 14%
ordinary text without R code
|................... | 29%
label: setup (with options)
List of 2
$ include: logi FALSE
$ indent : chr " "
|............................ | 43%
ordinary text without R code
|..................................... | 57%
label: unnamed-chunk-1 (with options)
List of 1
$ indent: chr " "
|.............................................. | 71%
inline R code fragments
|........................................................ | 86%
label: unnamed-chunk-2 (with options)
List of 1
$ indent: chr " "
|.................................................................| 100%
inline R code fragments
output file: test.tex
[1] "test.tex"
Tex Output:
>texi2pdf("test.tex")
>
I am using MikTex 2.9,knitr 1.9, R 3.0.2 on Windows , can you please attach your log files then we can compare the differences if any

rmarkdown error with ggplot and png

I have tried (in vain) to produce a chart with ggplot in Rmarkdown.
The code is the following:
```{r,echo=FALSE}
#fig.width=12,fig.height=6
panel2$PlotSize<-round(log(panel2$BSFA0200),0)- min(round(log(panel2$BSFA0200),0))+1# set size of dots
panel2$PlotSize[panel2$PlotSize==-Inf]<-NA
panel2$PlotColour<-ifelse(panel2$PlotSize<7,1,panel2$PlotSize)
panel2$PlotSize<-as.factor(panel2$PlotSize)
panel2$PlotColour<-as.factor(panel2$PlotColour)
g1<-ggplot(data=panel2,aes(x=NFR,y=PROF7*100,size=PlotSize,colour=PlotSize))+ geom_point()
g1
```
Out of knits this works fine, however when executed within a Rmd file (either as html or pdf) I always get this error message
processing file: 1Profti_model.Rmd
|.. | 4%
ordinary text without R code
|..... | 8%
label: setup (with options)
List of 1
$ include: logi FALSE
|........ | 12%
ordinary text without R code
|.......... | 15%
label: unnamed-chunk-1 (with options)
List of 3
$ echo : logi FALSE
$ warning: logi FALSE
$ message: logi FALSE
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
Loading required package: zoo
Attaching package: 'zoo'
The following objects are masked from 'package:base':
as.Date, as.Date.numeric
|............ | 19%
inline R code fragments
|............... | 23%
label: unnamed-chunk-2 (with options)
List of 1
$ echo: logi FALSE
|.................. | 27%
ordinary text without R code
|.................... | 31%
label: unnamed-chunk-3 (with options)
List of 1
$ echo: logi FALSE
Quitting from lines 98-109 (1Profti_model.Rmd)
Error in png(..., res = dpi, units = "in") : unable to start png() device
Calls: <Anonymous> ... in_dir -> plot2dev -> do.call -> <Anonymous> -> png
In addition: Warning messages:
1: Removed 55 rows containing missing values (geom_point).
2: In png(..., res = dpi, units = "in") :
unable to open file '1Profti_model_files/figure-html/unnamed-chunk-3-1.png' for writing
3: In png(..., res = dpi, units = "in") : opening device failed
Execution halted
I also tried to work around the problem by saving the chart in a png and load it as picture afterwards. Also no results (see Error with loading png in Rmd file)
Thanks for your help
UPDATE:
Following the suggestions from some of you guys I added a different chunk name and I replicated the code from Davit on my data (see updated code).
Unfortunately the error is still there. Interestingly, knitr cannot write a png but can write a csv in the same folder where the code is (I tested it).
Finally, i tested running this very same code onto my C drive and (surprise!) it works. However, this is for me not very efficient as I don't want to be dependent on a specific machine and I need to share this work with others (so network drive is a must). Moreover, all other package/code work fine in the network drive, only this png() seems to be an issue.
Thanks in advance for you help!
---
title: New Document
author: Me
output:
html_document
---
```{r prova,echo=FALSE, results='asis', message = FALSE, error = FALSE, warning= FALSE}
#.libPaths("D:/xxxx/packages")
require(ggplot2)
panel2 <- data.frame(BSFA0200 = rnorm(100),
NFR = rnorm(100),
PROF7 = rnorm(100))
panel2$PlotSize<-round(log(panel2$BSFA0200),0)- min(round(log(panel2$BSFA0200),0))+1# set size of dots
panel2$PlotSize[panel2$PlotSize==-Inf]<-NA
panel2$PlotColour<-ifelse(panel2$PlotSize<7,2,panel2$PlotSize)
write.csv(panel2[1:100,c('BSFA0200',"NFR","PROF7")],file="test.csv")
g1 <- ggplot(data = panel2,
aes(x = NFR,
y = PROF7 * 100,
size = factor(PlotSize),
colour = factor(PlotSize)
))
g1 + geom_point()
```
Error output:
Loading required package: ggplot2
Quitting from lines 9-32 (test.Rmd)
Error in png(..., res = dpi, units = "in") : unable to start png() device
Calls: <Anonymous> ... in_dir -> plot2dev -> do.call -> <Anonymous> -> png
In addition: Warning messages:
1: Removed 35 rows containing missing values (geom_point).
2: In png(..., res = dpi, units = "in") :
unable to open file 'test_files/figure-html/prova-1.png' for writing
3: In png(..., res = dpi, units = "in") : opening device failed
Execution halted
My knitr version is 1.11 (it should be the latest) and R version is 3.2.2
> R.Version()
$platform
[1] "i386-w64-mingw32"
$arch
[1] "i386"
$os
[1] "mingw32"
$system
[1] "i386, mingw32"
$status
[1] ""
$major
[1] "3"
$minor
[1] "2.2"
$year
[1] "2015"
$month
[1] "08"
$day
[1] "14"
$`svn rev`
[1] "69053"
$language
[1] "R"
$version.string
[1] "R version 3.2.2 (2015-08-14)"
$nickname
[1] "Fire Safety"
I got this message as well. The trouble with mine was that the file path was too long. I had my R markdown file in too many sub folders and the name of my R markdown file was too long. Once I reduced the length of the file path, the problem was resolved. I hope that works for you.
I had this same issue once. The code below works. You either had bad header or didn't call the packages: it's hard to tell since you did not provide that information. Also, please post example data next time.
Here is the full code that works (at least for me). If it doesn't run on your machine, post your data and full Rmd script and I'll try to help.
---
title: New Document
author: Me
output:
html_document
---
```{r,echo=FALSE, results='asis', message = FALSE, error = FALSE, warning= FALSE}
require(ggplot2)
panel2 <- data.frame(BSFA0200 = rnorm(100),
NFR = rnorm(100),
PROF7 = rnorm(100),
PlotSize = factor(rep(1:10, 10)),
PlotColour = factor(1:100))
g1 <- ggplot(data = panel2,
aes(x = NFR,
y = PROF7 * 100,
size = PlotSize,
colour = PlotSize))
g1 + geom_point()
```
I have also received this error; I solved it by moving the code to generate the offending figure into its own chunk.
I had a similar problem recently. And in my case, the issue was that antivirus software blocked Rscript.exe while it was trying to process files while knitting and PNG file was not created. So sometimes it is useful to temporarily disable antivirus and check if this solves the issue.
I have struggled with the same error. I understood it was something related to the path but couldn't solve it. Looking at the comments here, I tried closing the software and reopening it. It worked quickly. If this helps someone!

Resources