I have to simulate an image with a white crack on a black background. So I defined a function that adds to a matrix with all elements equal to zero some consecutive points equal to one.
The function is the following:
crepa<-function(matrice) {
start<-sample(1:ncol(matrice),1)
matrice[1,start]<-1
for (i in 2:nrow(matrice)) {
alpha<-sample(c(-1,0,1),1)
succ<-start+alpha
if (succ==(ncol(matrice)+1)) succ==ncol(matrice)
if (succ==0) succ==1
matrice[i,succ]<-1
start<-succ
}
matrice<-as.matrix(matrice)
}
To control whether the function works well, I applied it over and over again to the following matrix:
m<-matrix(0,64,64)
imma<-crepa(m)
par(mar=rep(0,4))
image(t(imma), axes = FALSE, col = grey(seq(0, 1, length = 256)))
In most cases the result is correct. However, in few cases I run into this Error:
Error in [<-(*tmp*, i, succ, value = 1) : subscript out of bounds
These two lines:
if (succ==(ncol(matrice)+1)) succ==ncol(matrice)
if (succ==0) succ==1
Should be:
if (succ==(ncol(matrice)+1)) succ=ncol(matrice)
if (succ==0) succ=1
In case you still can't see it, you've used the equality test == when you should use assignment = or <-.
The error message told me it had to be the element going off the matrix, so I started printing out the values of succ and then noticed it wasn't being reset within the right range, and only then did I spot the mistake. I probably looked at the code ten times without noticing. I also figured that kind of error was more likely with a small matrix, and so tested with a 6x6 matrix which meant I could be more likely to see it than with a 64x64!
Related
Given a -log10(P) value, I'd like to calculate the Z score in log space, how would I do that?
So, given the following code, how to recode the last line so that it calculates Z from log10P in the log space?
Z=10
log10P = -1*(pnorm(-abs(Z),log.p = T)*1/log(10) + log10(2))
Z== -1*(qnorm(10^-log10P/2)) # <- this needs to be in log space.
qnorm also has a log.p argument analogous to pnorm's, so you can reverse the operations that you used to get log10P in the first place (it took me a couple of tries to get this right ...)
I rearranged your log10P calculation slightly.
log10P_from_Z <- function(Z) {
abs((pnorm(-abs(Z),log.p=TRUE)+log(2))/log(10))
}
Z_from_log10P <- function(log10P) {
-1*qnorm(-(log10P*log(10))-log(2), log.p=TRUE)
}
We can check the round-trip accuracy (i.e. convert from -log10(p) to Z and back, see how close we got to the original value.) This works perfectly for values around 20, but does incur a little bit of round-off error for large values (would have to look more carefully to see if there's anything that can be remedied here).
zvec <- seq(20,400)
err <- sapply(zvec, function(z) {
abs(Z_from_log10P(log10P_from_Z(z))-z)
})
Suppose you want to program an R function that uses an argument with different possible spellings (e.g., using the arguments centre and center from British and US English respectively). You want the function to allow the user to use either spelling, but treated essentially as a single argument. What is "best practice" for how to structure a function like this?
Whilst I cannot speak to best practice, I am going to give one possible structure for this task, which seems to me to accommodate spelling variations. This is the method that is used in some of the base R functions for probability distributions when there are alternative parameterisations of the distribution (e.g., in the gamma distribution you can specify a scale or rate parameter). In these cases the function includes both arguments and then uses a clever set of commands to ensure that the function will use whichever argument is specified by the user.
To create a function using centre and centre as spelling variations for the same argument, you could use the structure shown below. Note that the computation in this method is done using the second spelling variation, and this latter argument is set equal to the former argument in the default values for the function. This ensures that the function will use the user-specified argument.
MY_FUNCTION <- function(centre = 0, center = centre, ...) {
#Check inputs
if (!missing(centre) && !missing(center)) {
if (sum((centre - center)^2) < 1e-15) {
warning("specify 'centre' or 'center' but not both") } else {
stop("Error: specify 'centre' or 'center' but not both") } }
Do some computations using the 'center' argument and then give output }
Here is an example of this function structure applied to generate a function DISTANCE that computes the Euclidean distance between a point and a centre/centre.
DISTANCE <- function(point, centre = 0, center = centre, ...) {
#Check inputs
if (!missing(centre) && !missing(center)) {
if (sum((centre - center)^2) < 1e-15) {
warning("specify 'centre' or 'center' but not both") } else {
stop("Error: specify 'centre' or 'center' but not both") } }
sqrt(sum((point - center)^2)) }
In the examples below, we demonstrate that this structure works properly regardless of whether the user uses the centre argument or the center argument. In the pathological case where the user specifies both arguments (which they really shouldn't) the function compares the values center and centre; if the values are close together then the function continues but gives the user a warning not to specify both arguments; if the values are not close together then the function stops and gives an error message telling the user not to specify both arguments.
POINT <- c(4, 2, 3);
CENT <- c(0, 3, 1);
DISTANCE(point = POINT, centre = CENT);
[1] 4.582576
DISTANCE(point = POINT, center = CENT);
[1] 4.582576
DISTANCE(point = POINT, centre = CENT, center = CENT);
[1] 4.582576
Warning message:
In DISTANCE(point = POINT, centre = CENT, center = CENT) :
specify 'centre' or 'center' but not both
DISTANCE(point = POINT, centre = CENT, center = CENT + 1);
Error in DISTANCE(point = POINT, centre = CENT, centre = CENT + 1) :
Error: specify 'centre' or 'center' but not both
I am working on a script that should estimate the probability of having at least 2 out of n people having a same birthday within k days from eachother. To estimate this I have the following function:
birthdayRangeCheck.prob = function(nPeople, seperation, nSimulations) {
count = 0
for (i in 1:nSimulations) {
count = count + birthdayRangeCheck(nPeople, seperation)
}
return(count / nSimulations)
}
Now just entering simple values for nPeople, seperation, nSimulations gives me a normal number.
e.g.
birthdayRangeCheck.prob(10,4,100)
-> 0.75
However when I want to plot the probability as a function of nPeople, and seperation I stumble upon the following problem:
x = 1:999
y = 0:998
z = outer(X = x, Y = y, FUN = birthdayRangeCheck.prob, nSimulations = 100)
numerical expression has 576 elements: only the first used... (a lot of times)
So it seems like outer is not entering single elements of x and y, but rather the vectors themselfs, which is the opposite of what outer should do right?
Am I overlooking something? Because I can't figure out what is causing this error. (replacing FUN with e.g. sin(x+y) works like a charm so I did pin it down to the function itself. But since the function works just fine with numeric arguments I don't see why R doesn't understand to just enter elements of x and y as arguments.)
Any help would be greatly appreciated. Thanks ;)
I am using the plotrix package to make the polar coordinates from my measurements.
It looks that even when I provide measurements for all the polar cordinates from 1 to 360 degrees (or equally to 0 to 359) the first and last points are not connected. For example
require(plotrix)
polar.plot(seq(1,360),polar.pos=1:360,radial.lim=c(0,361),rp.type="l")
A quick and dirty fix I found was to add one more measurement point, so instead of 360 use 361
as
polar.plot(seq(1,360),polar.pos=0:360,radial.lim=c(0,361),rp.type="l")
which gives warning messages.
Warning messages:
1: In cos(radial.pos[i, ]) * lengths[i, ] :
longer object length is not a multiple of shorter object length
2: In sin(radial.pos[i, ]) * lengths[i, ] :
longer object length is not a multiple of shorter object length
Are there any alternatives since showing my end user warning messages is not something that I like to see :)
I would like to thank you for your reply
Regards
Alex
It's going to connect them in order. So, if you want the final vertical line back to the origin, you need to add a datapoint at the end of the vector to make it do so. The error you got is that you added an extra value to one coord but not the other, so x and y are not equal. It recycled one of the vectors to fill it out, which happened to give you what you wanted, but gave you a warning that it was doing so.
polar.plot(c(seq(1,360), 1),
polar.pos = c(1:360, 1),
radial.lim = c(0,361),
rp.type = "l")
Hi I'm trying to write the bisection method using R. I know there has been questions like this before, but my specific questions is that, how could I write the function if specifying the midpoint and length, but not a and b? Here is my code, but it gives me lots of error.
The reason why I want to specify the midpoint and length is that, if the initial interval does not contain the root, it could double the search length... like from (pt-h/2, pt+h/2) to (pt-3h/2,pt+3h/2).
Here is my codes.
f1<-function(x){exp(x)-1}
find<-function(pt,h,tol = 0.0001){
if f1(pt-h/2)*f1(pt+h/2)<0{
time = 1
while (h>tol) {
if f1(pt)*f1(pt-h/2)<0 pt+h/2<-pt
if f1(pt)*f1(pt+h/2)<0 pt-h/2<-pt
time<-time+1
}
cat("Iteration time is ",time,"\n")
cat("The root is ",md,"\n")
cat("The real y of root is ",fmd,"\n")
}
}