How to start debugger only when condition is met - r

Assume I have a function which uses a loop over integer i. Now something goes wrong and I assume the error happens when i=5. Now I can step through every single step (what I did up to now).
But now I read about the condition and text argument of browser and debug:
text a text string that can be retrieved when the browser is
entered.
condition a condition that can be retrieved when the browser
is entered.
Is it possible to use the arguments in a way it works as I want?
Here is an example. The debugger / browser should only start after i=5 is reached:
fun <- function(x, y, n) {
result <- 0
for (i in 1:n) {
# browser(condition = (i == 5)) # does not work
result <- result + i * ( x + y)
}
return(result)
}
x <- 2
y <- 3
n <- 10
# debug(fun, condition = (i == 5)) # does not work
debug(fun)
r <- fun(x, y, n)
print(r)
The solution
if (i == 5) { # inside loop of fun()
browser()
}
is working, but I thougt there might be something better (No extra code inside the function)

You can use the argument expr in browser():
fun <- function(x, y, n) {
result <- 0
for (i in 1:n) {
browser(expr = {i == 5})
result <- result + i * ( x + y)
}
return(result)
}
It will then only open the environment where browser() was called from if the expression evaluates to TRUE.
If you want to use debug():
debug(fun, condition = i == 5)
and then call the function:
fun <- function(x, y, n) {
result <- 0
for (i in 1:n) {
result <- result + i * ( x + y)
}
return(result)
}
fun(x, y, n)

Use advanced features of trace().
First, identify the line of your function to debug, following the help page instructions for the argument at =, leading to at = list(c(3, 4))
> as.list(body(fun))
[[1]]
`{`
[[2]]
result <- 0
[[3]]
for (i in 1:n) {
result <- result + i * (x + y)
}
[[4]]
return(result)
> as.list(body(fun)[[3]])
[[1]]
`for`
[[2]]
i
[[3]]
1:n
[[4]]
{
result <- result + i * (x + y)
}
Next, specify a conditional break point by providing as the tracer= argument an unevaluated expression that invokes the browser when a specific condition is met, tracer = quote(if (i == 3) browser())
So
> trace(fun, tracer = quote(if (i == 3) browser()), at=list(c(3, 4)), print=FALSE)
[1] "fun"
> r <- fun(x, y, n)
Called from: eval(expr, p)
Browse[1]>
debug: {
result <- result + i * (x + y)
}
Browse[2]> i
[1] 3
Browse[2]> result
[1] 15
Browse[2]>

Related

function assignment error in a vector(R language)

i need to find the number 35 in x and assign it a function.
Then call the function.
code:
x <- 1:100
z <- 0
z[x == 35] <- function() { # error here
print("hello")
}
z <- max(z, na.rm=TRUE) # remove all NA in vector
z() # run it
error:
Error in z[x == 35] <- function() { :
incompatible types (from closure to double) in subassignment type fix
Thanks!!
Quite why you'd want to do it, but...
x <- 1:100
z <- list()
z[[which(x == 35)]] <- function() {
print("hello")
}
z[[which(x == 35)]]() # run it
[1] "hello"
The key is to use a list, not a vector.
Do you mean something like this?
z <- function(x) {
print("hello")
max(x, na.rm=TRUE) # remove all NA in vector
}
for (x in 1:100){
if (x == 35){
z(x)
}
}

Change a function to a numeric value

I have a function called in the example fn_example_1 that needs to change with a parameter that comes from another function (n).
It needs to have a fixed part that never changes, and a variable part that gets longer with n, as an example:
# this is the function that needs to change
fn_example_1 <- function(x, mod) {
# -- this part is fixed
mod$a <- x^2 # fixed
# -- this part can change with n
mod$b[5,5, k] <- x + 1 # variable
mod$b[6, 6, k] <- x + 1 # variable
# mod$b[7,7, k] <- x + 1 # if n = 3 ecc..
# k is an arg from a third function, more on that later..
mod
}
This is what I have in mind, basically a wrapper function that gives back a different version of fn_example_1 that depens on n.
fn_wrap_example <- function(fn, n) {
# something
# something
# I've thought about a long if else, of course with a max value for n.
return(fn)
}
fn_wrap_example(fn_example_1, n = 2) # call to the wrapper
It is crucial that fn_wrap_example returns a function, this will be an argument to a third function. As a semplification n can have a max value, ie: 20.
The key is that fn_example_1 is a function that changes with n.
Here is how you can modify a function in your wrapper:
fn_factory <- function(n) {
fn <- function(x, mod) {
# -- this part is fixed
mod$a <- x^2 # fixed
x #place holder
# k is an arg from a third function, more on that later..
mod
}
ins <- switch(n,
"1" = quote(mod$b[5,5, k] <- x + 1),
"2" = quote(mod$b[6, 6, k] <- x + 1)
)
body(fn)[[3]] <- ins
return(fn)
}
fn_factory(2)
#function (x, mod)
#{
# mod$a <- x^2
# mod$b[6, 6, k] <- x + 1
# mod
#}
#<environment: 0x0000000008334eb8>
I seriously doubt you need this, but it can of course be done.
What you are looking for is called a closure.
https://www.r-bloggers.com/closures-in-r-a-useful-abstraction/
http://adv-r.had.co.nz/Functional-programming.html
Simple example:
power <- function(exponent) {
function(x) {
x ^ exponent
}
}
square <- power(2)
square(2)

Error in if ((dimension < 1) | (dimension > n)) stop("wrong embedding dimension") : argument is of length zero

my code is like the following:
unemp <- c(1:10)
bsp_li <- list(c(1:10),c(11:20),c(21:30))
var_data_rep <- lapply(bsp_li, function(x) {cbind(as.numeric(x), as.numeric(unemp))} ) # Create VAR data matrices
var_data_rep2 <- lapply(var_data_rep, function(x) {colnames(x) = c("rGDP", "U"); return(x)}) # Name columns
var_data_rep_ts <- lapply(var_data_rep2, function(x) {ts(x, frequency=1, start=c(1977))} ) # Make it ts again
var_data_rep_lag <- lapply(var_data_rep_ts, function(x) {VARselect(x, lag.max = 5, type = "const")} ) # Take lag with lowest SC criteria (VAR.pdf)
VARgdp_rep <- lapply(var_data_rep_ts, function(x) {VAR(x, p = var_data_rep_lag$x$selection[['SC(n)']], type = "const"); return(x)} ) # Lag=lowest SC criteria from var_data_rep_lag
if i run only the last line r always gives me the error:
Error in if ((dimension < 1) | (dimension > n)) stop("wrong embedding dimension") :
argument is of length zero
Called from: embed(y, dimension = p + 1)
But if im running it with Source then it seems to work.. any suggestions?
This seems to work (at least no error is thrown) :
VARgdp_rep <-
lapply(index(var_data_rep_ts),
function(x) {
res <- VAR(var_data_rep_ts[[x]], p =
var_data_rep_lag[[x]]$selection[['SC(n)']], type = "const");
return(res)
}
)
In you code, return(x) is strange because after doing VAR calculations .. you just return the x withc was pass to the function.
And $x seems to have no meaning here.

Error in seq.default(a, length = max(0, b - a - 1)) : length must be non-negative number

I tried running the code below.
set.seed(307)
y<- rnorm(200)
h2=0.3773427
t=seq(-3.317670, 2.963407, length.out=500)
fit=density(y, bw=h2, n=1024, kernel="epanechnikov")
integrate.xy(fit$x, fit$y, min(fit$x), t[407])
However, i recived the following message:
"Error in seq.default(a, length = max(0, b - a - 1)) :
length must be non-negative number"
I am not sure what's wrong.
I do not encounter any problem when i use t[406] or t[408] as follow:
integrate.xy(fit$x, fit$y, min(fit$x), t[406])
integrate.xy(fit$x, fit$y, min(fit$x), t[408])
Does anyone know what's the problem and how to fix it? Appreciate your help please. Thanks!
I went through the source code for the integrate.xy function, and there seems to be a bug relating to the usage of the xtol argument.
For reference, here is the source code of integrate.xy function:
function (x, fx, a, b, use.spline = TRUE, xtol = 2e-08)
{
dig <- round(-log10(xtol))
f.match <- function(x, table) match(signif(x, dig), signif(table,
dig))
if (is.list(x)) {
fx <- x$y
x <- x$x
if (length(x) == 0)
stop("list 'x' has no valid $x component")
}
if ((n <- length(x)) != length(fx))
stop("'fx' must have same length as 'x'")
if (is.unsorted(x)) {
i <- sort.list(x)
x <- x[i]
fx <- fx[i]
}
if (any(i <- duplicated(x))) {
n <- length(x <- x[!i])
fx <- fx[!i]
}
if (any(diff(x) == 0))
stop("bug in 'duplicated()' killed me: have still multiple x[]!")
if (missing(a))
a <- x[1]
else if (any(a < x[1]))
stop("'a' must NOT be smaller than min(x)")
if (missing(b))
b <- x[n]
else if (any(b > x[n]))
stop("'b' must NOT be larger than max(x)")
if (length(a) != 1 && length(b) != 1 && length(a) != length(b))
stop("'a' and 'b' must have length 1 or same length !")
else {
k <- max(length(a), length(b))
if (any(b < a))
stop("'b' must be elementwise >= 'a'")
}
if (use.spline) {
xy <- spline(x, fx, n = max(1024, 3 * n))
if (xy$x[length(xy$x)] < x[n]) {
if (TRUE)
cat("working around spline(.) BUG --- hmm, really?\n\n")
xy$x <- c(xy$x, x[n])
xy$y <- c(xy$y, fx[n])
}
x <- xy$x
fx <- xy$y
n <- length(x)
}
ab <- unique(c(a, b))
xtol <- xtol * max(b - a)
BB <- abs(outer(x, ab, "-")) < xtol
if (any(j <- 0 == apply(BB, 2, sum))) {
y <- approx(x, fx, xout = ab[j])$y
x <- c(ab[j], x)
i <- sort.list(x)
x <- x[i]
fx <- c(y, fx)[i]
n <- length(x)
}
ai <- rep(f.match(a, x), length = k)
bi <- rep(f.match(b, x), length = k)
dfx <- fx[-c(1, n)] * diff(x, lag = 2)
r <- numeric(k)
for (i in 1:k) {
a <- ai[i]
b <- bi[i]
r[i] <- (x[a + 1] - x[a]) * fx[a] + (x[b] - x[b - 1]) *
fx[b] + sum(dfx[seq(a, length = max(0, b - a - 1))])
}
r/2
}
The value given to the xtol argument, is being overwritten in the line xtol <- xtol * max(b - a). But the value of the dig variable is calculated based on the original value of xtol, as given in the input to the function. Because of this mismatch, f.match function, in the line bi <- rep(f.match(b, x), length = k), returns no matches between x and b (i.e., NA). This results in the error that you have encountered.
A simple fix, at least for the case in question, would be to remove the xtol <- xtol * max(b - a) line. But, you should file a bug report with the maintainer of this package, for a more rigorous fix.

change argument names inside a function r

I'm trying to adjust the names of an argument inside a function. I want to create a procedure that takes the body of a function, looks for x, changes every x into x0, and then restores the function to what it was before. To provide an example:
f = function(x, y) -x^2 + x + -y^2 + y
# Take old names
form_old = names(formals(f))
# Make new names
form_new = paste0(form_old, 0)
# Give f new formals
formals(f) = setNames(vector("list", length(form_new)), form_new)
# Copy function body
bod = as.list(body(f))
for (i in 1:length(form_new)) {
bod = gsub(form_old[i], form_new[i], bod)
}
# return from list to call ?
body(f) = as.call(list(bod))
f(1, 1) # produces an error
So far, this code will change all variable names from x to x0 and from y to y0. However, the final output of bod is a character vector and not a call. How can I now change this back to a call?
Thanks in advance!
Surely there is a better way to do what you are trying to do that doesn't require modifying functions. That being said, you definetly don't want to be replacing variables by regular expressions, that could have all sorts of problems. Generally, trying to manipulate code as strings is going to lead to problems, for example, a function like tricky <- function(x, y) { tst <- "x + y"; -xx*x + yy*y }, where there are strings and variable names overlap, will lead to the wrong results.
Here is a function that takes a recursive approach (Recall) to traverse the expression tree (recursion could be avoided using a 'stack' type structure, but it seems more difficult to me).
## Function to replace variables in function body
## expr is `body(f)`, keyvals is a lookup table for replacements
rep_vars <- function(expr, keyvals) {
if (!length(expr)) return()
for (i in seq_along(expr)) {
if (is.call(expr[[i]])) expr[[i]][-1L] <- Recall(expr[[i]][-1L], keyvals)
if (is.name(expr[[i]]) && deparse(expr[[i]]) %in% names(keyvals))
expr[[i]] <- as.name(keyvals[[deparse(expr[[i]])]])
}
return( expr )
}
## Test it
f <- function(x, y) -x^2 + x + -y^2 + y
newvals <- c('x'='x0', 'y'='y0') # named lookup vector
newbod <- rep_vars(body(f), newvals)
newbod
# -x0^2 + x0 + -y0^2 + y0
## Rename the formals, and update the body
formals(f) <- pairlist(x0=bquote(), y0=bquote())
body(f) <- newbod
## The new 'f'
f
# function (x0, y0)
# -x0^2 + x0 + -y0^2 + y0
f(2, 2)
# [1] -4
With a more difficult function, where you want to avoid modifying strings or the other variables named yy and xx for example,
tricky <- function(x, y) { tst <- "x + y"; -xx*x + yy*y }
formals(tricky) <- pairlist(x0=bquote(), y0=bquote())
body(tricky) <- rep_vars(body(tricky), newvals)
tricky
# function (x0, y0)
# {
# tst <- "x + y"
# -xx * x0 + yy * y0
# }
#
There are a few ways to go here. Following your code, I would go with something like this:
f = function(x, y) -x^2 + x + -y^2 + y
# Take old names
form_old = names(formals(f))
# Make new names
form_new = paste0(form_old, 0)
deparse(body(f)) -> bod
for (i in 1:length(form_new)) {
bod = gsub(form_old[i], form_new[i], bod, fixed = TRUE)
}
formals(f) = setNames(vector("list", length(form_new)), form_new)
body(f) <- parse(text = bod)
f(1, 1)

Resources