r function in function arguments + apply - r

I'm having troubles using several functions within the same one and calling the arguments generated. I'm using a more complicated function that can be simplified as followed:
func.essai <- function(x) {
g <- sample(seq(1,30), x)
i <- sample(x,1)
func.essai.2 <- function(y,i) {
z <- y+i
}
h <- sapply(g,func.essai.2(y,i))
}
sq <- seq(1,4)
lapply(sq, func.essai)
I'm using arguments that are generated at the beginning of func.essai (and that depend on x) as a fixed input for func.essai.2, here for i, and as a vector to go through on the sapply function, here for g. This code doesn't work as such -- it doesn't recognize y and/or i. How can I rewrite the code to do so?

I think the error you get is because of your use of sapply. This should work instead of your line containing sapply:
h <- sapply(g,func.essai.2, i)
See ?sapply, which tells you that you should provide additional arguments behind the function that you are applying.

Related

Error in genereting_fuction(100) : could not find function "genereting_fuction

I created this function to generate the data with the characteristics I need:
genereting_fuction<-function(n){
X1=rnorm(n)+mean_shifts[1]
X4=rnorm(n)+mean_shifts[4]
X2=X1*p12+std_e2*rnorm(n)+mean_shifts[2]
X3=X1*p13+X4*p43+std_e3*rnorm(n)+mean_shifts[3]
X5=X2*p25+X3*p35+std_e5*rnorm(n)+mean_shifts[5]
sample=cbind(X1,X2,X3,X4,X5)
return(sample)
}
if I call it for a single item it works but when I call it in the applay function as follows:
dati<-lapply(1:100, genereting_fuction(100))
I get this error:
Error in genereting_fuction(100) :
could not find function "genereting_fuction"
Note that I prefer the replicate solution by #Jakub.Novotny for your purpose, but to understand what went wrong using lapply, this is why and how to solve it.
Using apply and a function, it assumes x the value of your apply to be provided always in the function.
To make it work you can do two things.
lapply(1:100, function(x) genereting_fuction(100))
include x in your function like genereting_fuction <- function(x, n) { # code here } and then you can use lapply(1:100, genereting_fuction, n = 100)

Use deriv or D as part of a function

I have got the following problem. I am trying to compute a function like:
derivation <- function(function, number) {
derivation <- deriv(~function, "x")
return(derivation(number))
}
For example:
derivation(x^2, 3) {
derivation <- 2*x
return(2*3)
}
I don't care if I have to put the function in the beginning in braces or as an expression. The variable will always be x. Also be open to use D.
One possibility:
f <- function(fun,val) {
expr <- substitute(fun)
d <- deriv(expr,"x",function.arg=TRUE)
g <- attr(d(val),"gradient")
return(g)
}
f(x^2,3)
substitute() converts the argument fun to an expression without evaluating it
deriv(...,function.arg=TRUE) returns a function that computes the value and includes the derivative as an attribute
d(val) calls the function
attr(.,"gradient") extracts the gradient
If you want to return both the function value and its gradient (as a two-element vector), you could use
r <- d(val)
return(c(c(r),attr(r,"gradient"))
in the function (the internal c(r) drops the attributes from r).

R argument is missing, with no default

I want to calculate the log return of data . I define a function and want to load the data. but system always mentions second factor is missing. Otherwise it just calculate the log of row number.
#read data
data <- read.csv(file="E:/Lect-1-TradingTS.csv",header=TRUE)
mode(data)
p<-data["Price"]
#func1
func1 <- function(x1,x2)
{
result <- log(x2)-log(x1)
return(result)
}
#calculate log return
log_return<-vector(mode="numeric", length=(nrow(data)-1))
for(i in 2:nrow(p))
{
log_return[i-1] <- func1(p[(i-1):i])
}
Error in func1(p[(i - 1):i]) : argument "x2" is missing, with no default
Your function func1 was defined to accept two arguments, but you are passing it a single argument: the vector p[(i-1):i], which has two elements but is still considered a single object. To fix this you need to pass two separate arguments, p[i-1] and p[i]. Alternatively, modify the definition of func1 to accept a two-element vector:
func1 <- function(v)
{
x1 <- v[1]
x2 <- v[2]
result <- log(x2)-log(x1)
return(result)
}
Thank you guys,all your answers inspired me. I think I found a solution.
log_return[i-1] <- func1(p[(i-1),"Price"],p[(i),"Price"])
basically you do not need a func for those calcs in R
R's vectorization comes in handy in these cases
data <- read.csv(file="E:/Lect-1-TradingTS.csv",header=TRUE)
mode(data)
p <- data[["Price"]]
logrets <- log(p[2:length(p)]) - log(p[1:length(p)-1])
This vectorized computation will usually also heavily outperform any function you define "by hand".

R: How to use as.call with vectors as optional parameters?

I'm trying to write a wrapper for a function in order to use lists as input. I cannot change the function itself, therefore I need a workaround outside of it. I use as.call() and it works without optional arguments, but I fail to make it work when I have vectors as optional arguments.
Example:
# function I cannot change
func <- function(..., opt=c(1,2)) {
cl <- match.call(expand.dots = FALSE)
names <- lapply(cl[[2]],as.character)
ev <- parent.frame()
classes <- unlist(lapply(names,function(name){class(get(name,envir=ev))}))
print(c(opt,names, classes))
}
a <- structure(1:3, class="My_Class")
b <- structure(letters[1:3], class="My_Class")
lst <- list(a, b)
names(lst) <- c("a","b")
# Normal result
func(a,b,opt=c(3,4))
# This should give the same but it doesn't
call <- as.call(append(list(func), list(names(lst), opt=c(3,4))))
g <- eval(call, lst)
Instead of a list as optional argument, I also tried c(), but this doesn't work either. Does anybody have a suggestion or a help page? ?call wasn't to clear about my problem.
(I already asked a previous question to the topic here: R: How to use list elements like arguments in ellipsis? , but left out the detail about the optional parameter and cannot figure it out now.)
This produces the same result for me under both versions
call <- as.call(c(list(quote(func)), lapply(names(lst), as.name), list(opt=c(3,4))))
g <- eval(call, lst)
EDIT: as per Hadley's suggestions in comments.

Initializing function arguments in the global environment R

I'm looking for a simple function to speed up my ability to write and debug R functions. Consider the following blocks of code:
# Part A:
myfun = function(a, b = 5, out = "hello"){
if(a>b) print(out)
return(a-b)
}
# Part B:
b = 5
out = "hello"
# Part C:
do.args = function(f){
#intialize the arguments of myfun in the parent environment
???
}
The function myfun is a trivial example of a bigger problem: I often have a complicated function with many arguments. To efficiently write and debug such a function, I find it useful to initialize the arguments of the function, and 'step through' the function line-by-line. Initializing the arguments, as in Part B above, is somewhat a hassle, when there are lots of arguments, and I would prefer to have a function as in Part C, which takes only the string myfun as it arguments and produces the same effect as running Part B in the current environment.
This only works for functions where all the arguments are defined. In other words, myfun has to have a value for a defined in the function.
some.func <- function(infunc){
forms <- formals(infunc)
for(i in 1:length(forms)){
assign(names(forms)[i],forms[[i]],envir=globalenv())
}
}
You could add a qualifier to deal with the variables that do not have default values, but it may not work in all examples. In this example I defined all missing variables to NA - and you could change the definition. Note: assigning the missing variables to NULL will not work.
some.func <- function(infunc){
forms <- formals(infunc)
for(i in 1:length(forms)){
if(class(forms[[i]])=="name") forms[[i]] <- NA
assign(names(forms)[i],forms[[i]],envir=globalenv())
}
}
You could also adjust the function and simply skip assigning the missing variables by using next after the if statement rather than defining the missing variables to NA, or some other value. The next example:
some.func <- function(infunc){
forms <- formals(infunc)
for(i in 1:length(forms)){
if(class(forms[[i]])=="name") next
assign(names(forms)[i],forms[[i]],envir=globalenv())
}
}
If you want to reassign formal arguments there is a formals<- function. By default the environment in which it does the assignment is the same as that in which it was created, bu that could be changed. See ?formals and ?alist
formals(myfun) <- alist(a=,b=4, out="not awake")
myfun
#------------------
function (a, b = 4, out = "not awake")
{
if (a > b)
print(out)
return(a - b)
You need to use alist with the argument of the form a= if you want the default to be missing.
}

Resources