So I'm kind of new to R, and I need to plot some functions. My understanding of curve in R is that it requires a function that has x as its single input. Since my functions are all just different representations of the same main function, I first thought I would create the main function, and then I would define each specific function individually.
# The principal function
puiss <- function(theta, inf, sup) {
for(k in inf:sup) {
total += (choose(30,k) * (theta^k) * ((1-theta)^(30-k)))
}
}
# The specific functions I need to draw on the same plot
p1 <- function(x) { puiss(x,2,13) }
p2 <- function(x) { puiss(x,3,14) }
p3 <- function(x) { puiss(x,3,13) }
# Can't even get to trace just a single one... :'(
curve(p1,
0, 1, # from 0 to 1
main="puissance(theta)", # title
xlab="x", ylab="theta") # axes
curve(p2, add=T) # adding the other function
curve(p3, add=T) # adding the other function
I get this error:
'expr' did not evaluate to an object of length 'n'
I've tried multiple approaches, but this one seemed to be the closest one to what it should have been.
Among other alternatives, I've tried:
changing from <- to = for the specific functions
using no {} (brackets) for the specific functions
plugging the for loop directly into the curve and replacing theta by x and inf:sup appropriately
trying to use p1(x) inside curve
I've also read that some times Vectorize() is needed, so I've tried Vectorize(p1) inside curve
What am I doing wrong?
It might help to disclose that my main function is just a Binomial(30, theta)'s mass function (probability) evaluated in different regions (the summation within the boundaries, my sigma which is a for loop because I couldn't figure out how to properly create a sigma function in R). In other words, it is a cumulative distribution function.
Ultimately, I'm trying to plot the 3 specific functions together on the same plot.
Thanks for the help! :)
It seems you are using some Python (or similar) code in your function definition.
Here is the R version of it, which for me will plot the results when calling curve.
puiss <- function(theta, inf, sup) {
total = 0
for(k in inf:sup) {
# "+=" does not work for R
total <- total + (choose(30,k) * (theta^k) * ((1-theta)^(30-k)))
}
# you need to use parentheses around total
return(total)
}
Related
Using R, before assessing some metric of accuracy on my own manual implementation of DFT, I wanted to do a sanity check on how well stats::fft() performs by doing the following:
sig.ts = ts( sin(2*pi*freq1*t) + sin(2*pi*freq2*t) );
sig.rt = fft(fft(sig.ts)/N, inverse="true");
#the two plots so perfectly align that you can't see them both
max(abs(sig.ts - sig.rt)) / max(sig.ts);
#arbitrary crude accuracy metric=1.230e-15 - EXCELLENT!
But I wanted to write the code for DFT myself, to ensure I understand it, then invert it in the hopes that it would be the same:
##The following is the slow DFT for now, not the FFT...
sR = 102.4; #the number of Hz at which we sample
freq1=3; freq2=12; #frequency(ies) of the wave
t = seq(1/sR,10, 1/sR);
sig.ts = ts( sin(2*pi*freq1*t) + sin(2*pi*freq2*t) );
N=length(t); kk=seq(0,N/2-1, 1); nn=seq(0,N-1, 1);
for(k in kk){
sig.freqd[k]=0;
for(n in nn){
sig.freqd[k] = sig.freqd[k] + sig.ts[n+1]*exp(-j*2*pi*n*k/N); } }
sig.freqd = (1/N)*sig.freqd; #for Normalization
#Checking the "accuracy" of my manual implementation of DFT...
sig.freqd_inv=Re(fft(sig.freqd, inverse="true"));
plot(t[1:100], window(sig.ts,end=100), col="black", type="l",lty=1,lwd=1, xaxt="n");
lines(t[1:100],window(sig.freqd_inv,end=100), col="red", type="l",lty=1,lwd=1, xaxt="n");
axis(1, at=seq(round(t[1],1),round(t[length(t)],1), by=0.1), las=2);
max(abs(sig.ts[1:(N/2-1)] - sig.freqd_inv)) / max(sig.ts[1:(N/2-1)]); #the metric here =1.482 unfortunately
Even without the metric, the plot makes it obvious that something's off here - it's lower amplitude, maybe out of phase, and more jagged. In all of my self-studying, I will say that I am a bit confused about how sensitive this all is to vector length..as well as how to ensure that the imaginary component's phase information is taken into account when plotting.
Bottom line, any insight into what's wrong with my DFT algorithm would be helpful. I don't want to just blackbox my use of functions - I want to understand these things more deeply before moving on to more complicated functions.
Thanks,
Christian
The main issues arise from the signal indexing. First to get a full transform usable by R's fft(..., inverse = TRUE), you would need to compute all N coefficients (even if the coefficients above N/2-1 could be obtained by symmetry).
Then you should realize that array indexing in R are 1-based. So, while indexing sig.freqd[k], the index k should start at 1 instead of 0. Since the argument to exp(-1i*2*pi*n*k/N) should start with n=0andk=0`, you'll need to adjust the indices:
kk=seq(1,N, 1); nn=seq(1,N, 1);
for(k in kk){
sig.freqd[k]=0i;
for(n in nn){
sig.freqd[k] = sig.freqd[k] + sig.ts[n]*exp(-1i*2*pi*(n-1)*(k-1)/N);
}
}
I've also changed you usage of j to represent the imaginary number 1i since that's the usual notation recognized by R (and R was complaining about it when trying your posted sample as-is). If you had defined j=1i that shouldn't affect the results.
Note also that R's fft is unnormalized. So to obtain the same result for the forward transform, your DFT implementation should not include the 1/N normalization. On the other hand, you will need to add this factor as a final step in order to get the full-circle forward+backward transform to match the original signal.
With these changes you should have the following code:
##The following is the slow DFT for now, not the FFT...
sR = 102.4; #the number of Hz at which we sample
freq1=3; freq2=12; #frequency(ies) of the wave
t = seq(1/sR,10, 1/sR);
sig.ts = ts( sin(2*pi*freq1*t) + sin(2*pi*freq2*t) );
N=length(t); kk=seq(1,N, 1); nn=seq(1,N, 1);
for(k in kk){
sig.freqd[k]=0i;
for(n in nn){
sig.freqd[k] = sig.freqd[k] + sig.ts[n]*exp(-1i*2*pi*(n-1)*(k-1)/N);
}
}
#Checking the "accuracy" of my manual implementation of DFT...
sig.freqd_inv=(1/N)*Re(fft(sig.freqd, inverse="true"));
plot(t[1:100], window(sig.ts,end=100), col="black", type="l",lty=1,lwd=2, xaxt="n");
lines(t[1:100],window(sig.freqd_inv,end=100), col="red", type="l",lty=2,lwd=1, xaxt="n");
axis(1, at=seq(round(t[1],1),round(t[length(t)],1), by=0.1), las=2);
max(abs(sig.ts - sig.freqd_inv)) / max(sig.ts)
This should yield a metric around 1.814886e-13, which is probably more in line with what you were expecting. The corresponding plot should also be showing the orignal signal and the roundtrip signal overlapping:
My problem is as it says in the title, I am trying to use the derivative (with respect to v) of the modified Bessel function of the second kind K_v(x) but with no success.
I read in one of the documentation that besselDK(v,x) would work as a derivative, apparently this is not a recognized function in R. I tried to use the expansion for the derivative, namely
besselK(v,x)*(1- (1/2v) -log(e*x/2v))
but this doesn't work to give me the correct plot as well. I am trying to plot a function which includes this.
P <- function(x) (1/2)*log(exp(1)/(2*pi*x^(2)))+(3*exp(1/x^(2))/(sqrt(2*pi*x^(2))))*besselK((1/x^(2)),1/2)*(log(exp(1)/x^(2)))
x <- seq(0.1,2,0.01)
plot(x, P(x), xlim=c(0,2), ylim=c(0,1.2), type="l")
From the code above, I get a straight line as a plot. In the correct plot, it should be a curve bending between 1 and 1.5, could someone please tell me the right way to go about it?
The derivative at nu = 1/2 is given here.
f <- function(nu,x){
besselK(x, nu)
}
library(gsl) # for expint_E1
fprime <- function(x){
sqrt(pi/2/x) * expint_E1(2*x) * exp(x)
}
nu <- 1/2
h <- 1e-6
x <- 2
(f(nu+h, x) - f(nu,x)) / h
## [1] 0.02474864
fprime(x)
## [1] 0.02474864
I am trying to find more efficient way(s) to fill an output matrix by applying a function to elements in a data.frame. I experimented with the apply() family functions and the outer() function but couldn't make them work.
Maybe someone here might be able to help? Here's a simplified version of my script. Thanks!
set.seed(192)
n = 1000
distMatrix <- matrix(nrow=n,ncol=n)
# Co-ordinates
coord <- data.frame(x = runif(n,min=0,max=n),
y = runif(n,min=0,max=n))
# Distance Function
distance <- function(A,B) { sqrt( (A['x']-B['x'])^2 + (A['y']-B['y'])^2 ) }
# Fill distMatrix -- this part could use better programming. Note that I am only
# filling the upper triangular part of distMatrix.
for (r in 1:(n-1)) {
for (c in (r+1):n) {
distMatrix[[r,c]] <- distance(coord[r,],coord[c,])
}
}
You can use:
distFun <- function(A,B)
sqrt(
(coord[A, "x"] - coord[B, "x"]) ^ 2 +
(coord[A, "y"] - coord[B, "y"]) ^ 2
)
distMatrix <- outer(1:nrow(coord), 1:nrow(coord), distFun)
Notice that we need to pass outer two vectors. Here we use the indeces of the rows of the data frame. outer then produces two new vectors that together represent every possible combination of our original vectors, and passes those to our function. Our function then pulls the relevant coordinates for our calculations (here coord is assumed to be defined ahead of the function).
One key thing to understand when using outer is that our function is called only once. outer just computes the vector inputs assuming our function is vectorized, and then applies the corresponding dimensions to the result.
Also, look at ?dist:
dist(coord)
Try it with a smaller matrix (maybe 10 by 10) to see the result.
I am trying to create a vector that will save the vector vprime for graphing later, but it wont't show up in my local environment (it is not writing the vector). Any ideas??
Thanks!!
###plot all three at once###
space<-seq(length=100, from=0, to=7.2) ##Create a sequence of 100 values ending at the point where value goes negative
A<- 4 #take a as given
alpha<-0.3 #take alpha as given
beta<-0.98 #take beta as given
vprime3 <- c(1:100) ##create a vector length 100 to be replaced later
t_vj3 <- c(1:100) ##create a vector length 100 to be replaced later
iterater<-function(space){ ##create a function to perform the iteration
for(i in 1:100){ ##create for loop for one of the state space (varying k+1)
for(j in 1:100){ ##create for loop for another axis of the state spcae (varying k)
if((A*(space[i]^alpha)-space[j])<0){ #plug in the law of motion
t_vj3[j]=-99 #and have a case for negative consumption so it does not take a negative log
}
else {
t_vj3[j+1] <- (log(A*(space[i]^alpha)-space[j])+ beta*t_vj3[j]) #have the law of motion for positive values
}
}
vprime3[i]<-max(t_vj3) #and create a vector of the maximum values, or the value functions
}
a4<-vprime3
plot(space,vprime3, type="p", xlab="State Space", ylab="Value") # and plot this graph
}
iterater(space) #call the function
It is creating the vector in the environment of the function body. That environment, and thus the vector goes away once the function returns.
There are two ways to get the value: Return the value and capture it, or modify the enclosing environment directly.
To return the value, change the function as follows:
iterater<-function(space){
# ....
a4<-vprime3
plot(space,vprime3, type="p", xlab="State Space", ylab="Value") # and plot this graph
# Added line
return(a4)
}
## Call iterater, saving the value:
a4 <- iterater(space)
Modifying the enclosing environment seems easy, but leads to trouble down the road, so this approach should be avoided. But to do this, change the function as follows:
iterater<-function(space){
# ....
# Note <<- instead of <-
a4<<-vprime3
plot(space,vprime3, type="p", xlab="State Space", ylab="Value") # and plot this graph
}
I'm trying to arcsine squareroot data lying on [-1,1]. Using transf.arcsine from the metafor package produces NaNs when trying to squareroot the negative datapoints. Conceptually, I want to use arcsin(sgn(x)√|x|) i.e. square the absolute value, apply its previous sign, then arcsine transform it. The trouble is I have no idea how to begin doing this in R. Help would be appreciated.
x <- seq(-1, 1, length = 20)
asin(sign(x) * sqrt(abs(x)))
or as a function
trans.arcsine <- function(x){
asin(sign(x) * sqrt(abs(x)))
}
trans.arcsine(x)
Help in R is just help() or help.search(). So, let's try the obvious,
> help(arcsin)
No documentation for ‘arcsin’ in specified packages and libraries:
OK, that's not good. But it must be able to trig... let's try something even simpler.
help(sin)
There's all the trig functions. And I note, there's a link to Math on the page. Clicking that seems to provide all of the functions you need. It turns out that I could have just typed..
help(Math)
also,
help.search('trigonometry')
I had a similar prob. I wanted to arcsine transform most of the dataset "logmeantd.ascvr" & approached it in this manner:
First make are data range has been transformed b/t -1 and 1 (in this case they were expressed as percentages):
logmeantd.ascvr[1:12] <- logmeantd.ascvr[1:12] * 0.01
Next apply the square root function, sqrt():
logmeantd.ascvr[1:12] <- sqrt(logmeantd.ascvr[1:12])
lastly apply the arc sine function, asin():
logmeantd.ascvr[1:12] <- asin(logmeantd.ascvr[1:12])
*note in this instance I had excluded the MEAN variable of my dataset because I wanted to apply a log function to it, log():
logmeantd.ascvr$MEAN <- log(logmeantd.ascvr$MEAN)