How can i dynamically generate a function-paramater in R?
I will use the paste0 function for different parameters for the line-function:
lines(paste0(gdaxisymbol[i],"$",gdaxisymbol[i],".Adjusted"))
It ends with an warning:
In xy.coords(x, y) : NAs durch Umwandlung erzeugt
thx
Hi, thx for your answer and sorry for the unclear question
Here is my full code:
library(XML)
library(RCurl)
s <- getURL("https://de.finance.yahoo.com/quote/^GDAXI/components")
t=readHTMLTable(s)
gdaxi = t[["NULL"]]
gdaxi = gdaxi[,-(3:6) ]
gdaxisymbol <- gdaxi$Symbol
getSymbols(gdaxisymbol,from="2015-12-31",to="2021-01-31", auto.assign = TRUE)
plot(ADS.DE$ADS.DE.Adjusted)
for(i in 1:30)
{
lines(paste0(gdaxisymbol[i],"$",gdaxisymbol[i],".Adjusted"))
}
I would like to print all Adujsted share prices in one Plot.
But if i execute the loop i become the error above.
How can i give the correct parameter dynamicaly to the lines function?
If i print one line with
lines(ALV.DE$ALV.DE.Adjusted)
it works fine.
thx
This questions isn't perfectly clear. Not sure whether the problem is with the lines function or something else. But I'll answer the question regarding how to dynamically pass parameters for a function.
If you want to dynamically pass parameters for a function and send them into paste0, the easiest way to do it is to pass the parameters in on a list or vector. Here is an example:
# Define function
paste_special <- function(inputs) {
ret <- paste0(inputs, collapse = "")
return(ret)
}
# Create sample data
myinputs <- c("A", "$", "B", ".adjusted")
# Call function and view results
paste_special(myinputs)
# [1] "A$B.adjusted"
Since the list or vector is flexible, and can take any number of elements, then your function can also take any number of elements.
Related
I'm still new to writing my own functions. As an exercise and because I use it alot, I want to write a flexible function to easily reverse survey response scales. This is what I came up with:
rev_scale = function(var, new_var, scale){
for (i in 1:length(abs(var))){
new_var[i] = scale-abs(var[i])+1
}
}
Info on code
var = variable I want to reverse.
new_var = new column with the reversed variable
scale = how many points in the scale (eg. 5 for a 5-point scale)
The reason why I use 'abs' instead of just 'var' is that some dataframes also return value-labels, and I only want the values in this function.
Question
When applying this new function on a variable, R returns "NULL". However, if I run the for-loop separately, with the arguments 'imputed', my new variable is properly reversed.
Any ideas on what is happening here?
Thanks in advance!
### Example of the (working) for-loop with arguments 'imputed' ###
df <- data.frame(matrix(ncol = 1, nrow = 4))
df$var = c(1,2,3,4)
for (i in 1:length(abs(df$var))){
df$var_rev[i] = 4-abs(df$var[i])+1
}
df$var_rev
OUTPUT:
[1] 4 3 2 1
R does not use reference-variables (think pointers)*. So your new_var outside of your function does not get updated when refered to inside a function. Instead, R creates a new copy of new_var and updates that.
You should instead return the new value from your function. I.e.
rev_scale = function(var, scale){
res <- vector('numeric', length(var))
for (i in 1:length(abs(var))){
res[i] = scale-abs(var[i])+1
}
return(res)
}
Also note that I have removed new_var from the function's arguments. In other words, I have completely separated the functions input-arguments from its output.
The reason you get a NULL from the function is that in R, all functions returns somethings. If not specified, the function will return the last value of the last statement, except when the last statement is a control structure (ifs, loops) - then it defaults to a NULL.
* There are a couple of exceptions and work-arounds, but I will not go into that here.
Edit:
As benimwolfspelz noted, you do not need to explicitly iterate over each element in var, as R does this implicitly. Your entire function could be reduced to:
rev_scale = function(var, scale) {
scale-abs(var)+1
}
Secondly, in your for-loop, your can simplify length(abs(var)) to length(var) as abs(var) does not change the length of the vector.
I am trying to solve the following a constrained maximization problem.
The example here is simply me trying to recreate a simple example.
I have a dataframe as follows:
Obs=c(1,2,3,4,5)
Var1=c(11,15,16,19,20)
Var2=c(1.5,22,0.9,1.7,.1)
Var3=c(2.6,2.5,3.5,3.6,2.1)
Value_One = c(10,12.5,8.4,7.5,2.6)
Cost = c(1.1,1.2,1.3,1.6,1.7)
Value_overall = c(10,21,31,4,29)
df=data.frame(Obs,Var1,Var2,Var3,Value_One,Cost,Value_overall)
var_sel=c('Var1','Var2')
coeff_sel=c(2.5,4.5)
gamma=.7
I have to run a constrained optimization problem an example of which is as follows (Note the exact values, does not matter. Please feel free to change them as you please):
Value_func = function(x){
Value_var=x$Cost
# - since the contrained optimum function is for minima.
-((x$Value_overall+gamma*(x$Value_null-
(as.matrix(x[var_sel])%*%(as.matrix(coeff_sel)))))-2*x[Cost])
}
#Please feel free to change the values below.
#I just want to know where I am going wrong. The exact values do not matter here.
for (i2 in 1:nrow(df)){
x=df[i2,]
zzz=constrOptim(-1.2, Value_func, NULL,ui=1,ci=-1.3)
}
What I want to do is to run the above for each row of the dataframe. When I run the above example, I get the following error:
Error: $ operator is invalid for atomic vectors
Called from: f(theta, ...)
I tried to look for a solution and this is what I got but it does not seem to be applicable in my case (R $ operator is invalid for atomic vectors in constraOptim).
Please help. Thanks in advance.
This makes a result without error. Changes to your code include:
Added Value_null to the data.frame
Changed the function argument to costs and modify the function after the matrix stuff.
Saved the results to zzz as a list instead of static.
If you design this as a matrix in the first place, you could utilize apply.
df <- data.frame(Obs=c(1,2,3,4,5)
,Var1=c(11,15,16,19,20)
,Var2=c(1.5,22,0.9,1.7,.1)
,Var3=c(2.6,2.5,3.5,3.6,2.1)
,Value_One = c(10,12.5,8.4,7.5,2.6)
,Cost = c(1.1,1.2,1.3,1.6,1.7)
,Value_overall = c(10,21,31,4,29)
#added to match
,Value_null = 5
)
var_sel=c('Var1','Var2')
coeff_sel=c(2.5,4.5)
gamma=.7
Value_func = function(costs){
# - since the contrained optimum function is for minima.
-((x$Value_overall+gamma*(x$Value_null-
(as.matrix(x[var_sel])%*%(as.matrix(coeff_sel)))))-2*costs)
}
for (i2 in 1:nrow(df)){
x=df[i2,]
zzz[[i2]]=constrOptim(1, Value_func, NULL,ui=1,ci=-1.3, x$Cost)
}
Or the apply approach. I don't like that I'm assigning x <<- z but it gives results.
Value_func = function(costs){
# - since the contrained optimum function is for minima.
-((x['Value_overall']+gamma*(x['Value_null']-
(x[var_sel]%*%(coeff_sel))))-2*costs)
}
apply(df, 1, function(z) {
x<<- z
constrOptim(1, Value_func, NULL, ui = 1, ci = -1.3, z['Cost'])
}
)
In my code I have to create an object assigning some values, something like this:
assign(paste("a","bis",sep="."),rep(NA,5))
then I have to replace some of them, like this:
get(paste("a","bis",sep="."))[1:2] <- 7:8
But I get the following error: "Error in get(paste("a", "bis", sep = "."))[1:2] <- 7:8 : target of assignment expands to non-language object".
Of course the code above is a simplified version of the real one. What I'm trying to do is to build a loop which allows me to replace in a data frame the results of some calculations. Something like this
assign(paste(country[j],"ext",sep="."),
data.frame(Year=rep(unique(get(country[j])$Year),each=24),
Age=rep(c(0,1,seq(5,110,5)),length(unique(get(country[j])$Year))),
mx=NA,qx=NA,lx=NA,Lx=NA,Tx=NA,ex=NA))
get(paste(country[j],".ext",sep=""))$mx[(24*i-24+1):(24*i)] <-
c(subset(get(country[j]),Age<=70 & Year==year)$mx,mx.ext)
in this case, the error indicates that: *Error in get(paste(country[j], ".ext", sep = ""))$mx[(24 * i - 24 + 1):(24 * : could not find function "get<-"*
Thanks in advance.
You would be better off saving these items in a list.
myList <- list()
myList[[paste("a","bis",sep=".")]] <- rep(NA,5))
or
myList[[paste(country[j],"ext",sep=".")]] <- data.frame(Year=rep(unique(get(country[j])$Year),each=24),
Age=rep(c(0,1,seq(5,110,5)),length(unique(get(country[j])$Year))),
mx=NA,qx=NA,lx=NA,Lx=NA,Tx=NA,ex=NA))
This relieves you from the pains of get() and assign() and also puts your data in nice structure for looping / applying.
I'm using {manipulate} to add a number of check-boxes to the plot - one for each line that is being drawn. Since the number required is not pre-defined I'm trying to figure a way out to pass all checkboxes as a vector or a list to the manipulate function.
The documentation seems to hint something :
manipulate(_expr, ...)
_expr : Expression to evalulate.
... : One or more named control arguments (i.e. slider, picker, checkbox, or button), or a list containing named controls.
I think the way out would be to pass a list of as many checkboxes as is required. But how exactly should that be carried out?
The following example should do what you want:
# Define function for ploting
example <- function(...){
plot(cars)
i <- 1
for (my.control in list(...)) {
if (my.control) abline(0, i)
i <- i+1
}
}
# Define your controls
custom.args <- list()
for (i in 1:5) {
custom.args <- append(custom.args, list(checkbox(FALSE, paste("Ceckbox", i))))
}
names(custom.args) <- paste("checkbox", 1:5, sep="")
# Pass everything to manipulate
library(manipulate)
manipulate(
eval(parse(text=sprintf('example(%s)',
paste(names(custom.args), collapse=","))
)),
custom.args)
I don't know if there is a cleaner way to pass control values to plotting function, but at least this works.
I am writing a function where in one or more of the arguments are vectors generated by a loop within the function.
For ex:
myfunc<-function(rep, n, arm1, arm2)
{
for(i in 1:rep)
{
x<-rnorm(n,0,4)
y<-rnorm(n,0,5)
res[i]<-t.test(arm1,arm2)
}
return(res)
}
Now I would like to call the function as
myfunc(rep = 10, n=10, arm1 = x, arm2 = x) or
myfunc(rep = 10, n=10, arm1=x,arm2 = y)
The idea is compare different arms.
Hope I have stated my problem clearly.
Your help is highly appreciated.
Let's see if I got it...
You want run rep tests, each with two vetors of n normal random variates. And you want to be able to change the arguments... Frankly, this is not the best way to program.. BUT, I will try to help you.
First things first: you can't assign to an arbitrary position of the result res before creating the variable. So I'll add res <- list() to your code. Also t.test returns more information, so it must be appended to a list object, with double square brackets.
Now, for the arguments, you must make R understand that arm are symbol arguments, to be evaluated inside the function's environment. So you must capture it's expression using substitute and pass it to eval function:
myfunc<-function(rep, n, arm1, arm2)
{
res <- list() ###
for(i in 1:rep)
{
x<-rnorm(n,0,4)
y<-rnorm(n,0,5)
res[[i]]<-t.test(eval(substitute(arm1)),eval(substitute(arm2))) ###
}
return(res)
}
Try it...
A better way to do this is as follows:
newfunc <- function(rep, n, sd1, sd2)
{
lapply(1:rep, function(.) t.test(rnorm(n,0,sd1), rnorm(n,0,sd2)))
}
Now sd1 and sd2 are the standard deviations parameters.