How to implement a function with a sum inside in R? - r

I am trying to define a function with a for loop and inside a conditional in R studio. Yesterday I was able with the help of another thread to devise this piece of code. The problem is that I want to sum the vector elements ma for any possible x, so that is inside the function l. This is a simpler case which I am trying to solve to adapt the original model. However, I do not know how to proceed.
ma<-rep(0,20)
l <- function(x, ma) {
for(i in seq_along(ma)) {
if(i %% 2 == 1) {
ma[i] <- i + x
} else {
ma[i] <- 0
}
}
return(ma)
}
My problem is that I would like to have the sum of i+x+0+i+x... for any possible x. I mean a function of the kind for any possible x.
Question:
Can someone explain to me how to implement such a function in R?
Thanks in advance!
I am going to update the original function:
Theta_alpha_s<-function(s,alpha,t,Basis){
for (i in seq_along(Basis)){
if(i%% 2==1) {Basis[i]=s*i^{-alpha-0.5}*sqrt(2)*cos(2*pi*i*t)}
else{Basis[i]=s*i^{-alpha-0.5}*sqrt(2)*sin(2*pi*i*t)}
}
return(Basis)
}

If you don't want to change the values in Basis, you can create a new vector in the function (here result) that you will return:
l = function(s,alpha,t,Basis){
is.odd = which(Basis %% 2 == 1)
not.odd = which(Basis %% 2 == 0)
result = rep(NA, length(Basis))
result[is.odd] = s*is.odd^{-alpha-0.5}*sqrt(2)*cos(2*pi*is.odd*t)
result[not.odd] = s*not.odd^{-alpha-0.5}*sqrt(2)*sin(2*pi*not.odd*t)
#return(result)
return(c(sum(result[is.odd]), sum(result[not.odd])))
}

Related

why c() does not working in this recursive function in R?

enter image description here
I know there exists function 'unique' which works similar to what I want to make, but I want to make this function.
I want this function finally returns 'result' which contains unique elements of input vector.
But I don't know why this function's result is totally different from my expect.
Why c which is to combine before result and new unique element is not working.
Please tell me how to fix my code.
Thank you.
I think what you expect might be something like below, where result should be an argument of m_uni:
m_uni <- function(x,result = c()) {
if (class(x)=='numeric'| class(x)=='character') {
if (length(x) <= 1){
return(result)
} else {
if (x[length(x)] %in% result) {
x <- x[-length(x)]
m_uni(x,result)
} else {
result <- c(result,x[length(x)])
x <- x[-length(x)]
m_uni(x,result)
}
}
} else {
return('This function only gets numeric or character vector')
}
}
such that
> m_uni(x)
[1] 0 4 5 -2

R S3 cat() output from function

I've got a problem with output from S3 function. I try to overload "+" function to act with two vectors like with polynomial parameters. It's my university project. Code is below:
'+.ply' <- function(a,b){
size <- max(length(a$polynomial),length(b$polynomial))
size
aAdd <- a$polynomial
bAdd <- b$polynomial
if (length(aAdd) == size) {
aAdd = aAdd
} else {
length(aAdd) <- size
}
aAdd[is.na(aAdd)] <- 0
if (length(bAdd) == size) {
bAdd = bAdd
} else {
length(bAdd) <- size
}
bAdd[is.na(bAdd)] <- 0
cat("Polynomial of degree ", paste(length(aAdd+bAdd)-1),
" with coefficients ", paste(aAdd+bAdd))
}
Code is working fine, but in return it gives me output
*Polynomial of degree 3 with coefficients 3 4 6 3NULL*
I need to use cat in order to avoid [1] index which occurs while I'm using print, paste combo. I know that there are plenty threads about this problem, but I can't find any sollution for such problem during function overloading. I will be thankful for help.

Nested for-loops into apply?

I need help figuring out how to improve a for loop. It doesn't necessarily needs to be apply, I just thought it was the best way after researching it on StackOverflow. I tried following the guides I found on StackOverflow, but I'm a newbie and believe I'm not getting a good grasp on the apply function.
This is a reconstruction of the snippet I'm trying to change:
for (j in 1:NROW(teste2) {
for (z in 1:NROW(teste2)) {
if(is.na(teste2$DATE[z]==Sys.Date()+j-1) | z==NROW(teste2)){
teste2$SALDO[z] <- 0
}else{
if(teste2$SALDO[z]!=0 & teste2$DATE[z]==Sys.Date()+j-1){
teste2$SALDO[z+1] <- teste2$PREVISAO_FINAL2[z] + teste2$SALDO[z+1]
}else{
teste2$SALDO[z] <- teste2$SALDO[z]
}
}
}
I tried doing the following:
for (j in 1:NROW(teste2) {
rows = 1:NROW(teste2)
saldo_fn <- function(z){
return(if(is.na(teste2$DATE[z]==Sys.Date()+j-1) | z==NROW(teste2)){
teste2$SALDO[z] <- 0
}else{
if(teste2$SALDO[z]!=0 & teste2$DATE[z]==Sys.Date()+j-1){
teste2$SALDO[z+1] <- teste2$PREVISAO_FINAL2[z] + teste2$SALDO[z+1]
}else{
teste2$SALDO[z] <- teste2$SALDO[z]
}
})
}
teste2$SALDO <- sapply(rows, saldo_fn)
}
But when I run sum(teste2$SALDO) it gives a different value.
What am I doing wrong? how do I fix it?
You cannot use apply-family function to optimize the algorithm. The reason is the line:
teste2$SALDO[z+1] <- teste2$PREVISAO_FINAL2[z] + teste2$SALDO[z+1]
You are recursively changing the value of next element based on the value of current one.
It is possible avoid for-loop in by using recursion, i.e. if you see something like x[i+1] = x[i+1] + x[i] you should use either for-loops or recursive functions (I prefer for-loops they are much easier and there is no problem with call stack overflow), if you see something like z[i] = F(x[i], y[i]), where F is some function, you can use apply-family functions.

How to apply a running function inR

I need to develop a function in R which can be used to compute time varying variable API which is defines as: api(t)=k*api(t-1)+ppt(t).
ppt=round(c(0.0,0.0,0.0,runif(25, 0.0, 15.5),0.0,0.0),digit=1)
api=c(5.75,rep(NA,29))
k=0.85
f <- function(k,api,ppt,...){
for (i in 2:30){
api[i]=k*api[i-1]+ppt[i]
return(api)}}
f(k=k,api=api,ppt=ppt)
when I apply the above function I am only getting the first value.
I appreciate you help.
You can use simple recursion:
calculateP <- function(startP, t, k, j) {
if (t == 0) {
return (stp)
}
return (k[t]*calcP(stp, t-1, k,j) + j[t])
}
Seems to work pretty well.

How to setup a recursive lapply for specific values ex.w[i] == n[i]?

Background
I'm developing a function that takes in a value for w between 1 and 3 and returns n values from one of 3 distributions.
The problem I am having is when n or w are not of length 1. So I've added 2 parameters nIsList and wIsList to create the functionality I want. The way I want this to work is as follows:
(Works as needed)
If nIsList ex( c(1,2,3) ) return a list equivalent to running consume(w,1), consume(w,2), consume(w,3)
(Works as needed)
If wIsList ex( c(1,2,3) ) return a list equivalent to running consume(1,n), consume(2,n), consume(3,n)
(Doesn't work as needed)
If nIsList ex(1,2,3) and wIsList ex(1,2,3)
return a list equivalent to running consume(1,1), consume(2,2), consume(3,3). Instead, I get a list equivalent to running [consume(1,1), consume(1,2), consume(1,3)], [consume(2,1), consume(2,2), consume(2,3)], [consume(3,1),consume(3,2), consume(3,3)]
I understand why I am getting the results I am getting. I just can't seem to figure out how to get the result I want. (As explained above)
Question
I want the function to provide a list for each element in w and n that is consume(w[i], n[i]) when wIsList & nIsList are True. Is there a way to do that using lapply?
The code:
library("triangle")
consume <- function(w, n=1, nIsList=F, wIsList=F){
if(!nIsList & !wIsList){
if(w==1){
return(rtriangle(n,0.3,0.8))
}else if(w==2){
return(rtriangle(n,0.7,1))
}else if(w==3){
return(rtriangle(n,0.9,2,1.3))
}
}
else if(nIsList & !wIsList){
return(sapply(n, consume, w=w))
}
else if(nIsList & wIsList){
return(lapply(n, consume, w=w, wIsList=T))
}
else if(!nIsList & wIsList){
return(lapply(w, consume, n))
}
}
Note: I am having trouble summarizing this question. If you have any suggestions for renaming it please let me know and I will do so.
Thanks to JPC's comment, using mapply does the trick. The new code is as follows:
consume <- function(w, n=1){
nIsList <- length(n) > 1 # Change based on JPC's second comment
wIsList <- length(w) > 1 # Change based on JPC's second comment
if(!nIsList & !wIsList){
if(w==1){
return(rtriangle(n,0.3,0.8))
}else if(w==2){
return(rtriangle(n,0.7,1))
}else if(w==3){
return(rtriangle(n,0.9,2,1.3))
}
}
else if(nIsList & !wIsList){
return(sapply(n, consume, w=w))
}
else if(nIsList & wIsList){
return(mapply(consume,w,n)) ## Updated portion
}
else if(!nIsList & wIsList){
return(lapply(w, consume, n))
}
}

Resources