R: Apply function based on vector B to vector A - r

My first question...
I have two vectors, q and n. I want to perform a function on q based on the corresponding value in n (specifically binom.test(q[t],n[t],0.5)).
I've made a loop to do it, which works OK, but I'd like to know how to use apply functions to do it faster if such a thing is possible. I'm new to r, so please forgive my ignorance and probably sloppy formatting.
This is my loop:
q = ...
n = ...
p = c()
for(t in c(1:30)) {p = c(p,binom.test(q[t],n[t],0.5)$p.value)}
Thanks!

You can do this with sapply like this:
sapply(1:length(q), function(t) binom.test(q[t], n[t], 0.5)$p.value)

Related

Which loop to use, R language?

We have to create function(K) that returns vector which has all items smaller than or equal to K from fibonacci sequence. We can assume K is fibonacci item. For example if K is 3 the function would return vector (1,1,2,3).
In general, a for loop is used when you know how many iterations you need to do, and a while loop is used when you want to keep going until a condition is met.
For this case, it sounds like you get an input K and you want to keep going until you find a Fibonacci term > K, so use a while loop.
ans <- function(n) {
x <- c(1,1)
while (length(x) <= n) {
position <- length(x)
new <- x[position] + x[position-1]
x <- c(x,new)
}
return(x[x<=n])
}
`
Tried many different loops, and this is closest I get. It works with every other number but ans(3) gives 1,1,2 even though it should give 1,1,2,3. Couldn't see what is wrong with this.

How to create a function the finds the indexed slope of two vectors

I have looked everywhere for this answer but I am having a hard time even figuring our how to ask this question. I am trying to create a function such that it creates a vector that is a function of two other vectors, where I use a for loop to index values at k and k+1. Here is an example of my code, which does not work:
x <- 1:10
y <- x^2
d <- data.frame(x,y)
invSlope <- NULL
invSlope.f <- function(X,Y){
for(k in 1:length(X)-1){
invSlope[k] = (X[k+1] - X[k])/ (Y[k+1] - Y[k])
invSlope[length(X)] = 0
return(invSlope)
}
}
d$invSlope <- invSlope.f(d$x,d$y)
What I am trying to accomplish is at d$invSlope[1] I have the inverse of the slope of the line that comes after it (delta x/delta y). The last value of the vector would just be 0. I can accomplish this with a for loop (or even nested for loops), but I would like to generalize this to a function.
Thanks
The diff function is a vectorized approach... we don't need no steenkin' loops:
finvslope <- function(xseq, yseq) { c( diff(xseq)/diff(yseq) , 0) }

How to avoid a loop here in R?

In my R program I have a "for" loop of the following form:
for(i in 1:I)
{
res[i] <- a[i:I] %*% b[i:I]
}
where res, a and b are vectors of length I.
Is there any straightforward way to avoid this loop and calculate res directly? If so, would that be more efficient?
Thanks in advance!
This is the "reverse cumsum" of a*b
rev(cumsum(rev(a) * rev(b)))
So long as res is already of length I, the for loop isn't "incorrect" and the apply solutions will not really be any faster. However, using apply can be more succinct...(if potentially less readable)
Something like this:
res <- sapply(seq_along(a), function(i) a[i:I] %*% b[i:I])
should work as a one-liner.
Expanding on my first sentence. While using the inherent vectorization available in R is very handy and often the fastest way to go, it isn't always critical to avoid for loops. Underneath, the apply family determines the size of the output and pre-allocates it before "looping".

Applying a function to a random sample of vector elements

I have been learning R for the past few days, and want to find out whether the problem below can be solved in a better manner (compacter code perhaps) than my solution.
Problem: A vector V of N (~ 1000) numeric elements, needs to be transformed in the following way.
Choose M (~ 100) elements at random.
Replace each such element x with f(x).
My Solution: for (i in sample(1:N, M)) V[i] = f(V[i])
Edit: The function f takes as input a single numeric value, and also outputs a single numeric value. Something like: f <- function (x) x^3 + 2
Edit: Thanks for everyone's contributions! I now understand the power of vectorized functions. :)
How about this
i <- sample(1:N, M)
V[i] <- f(V[i])
No need for loop since [<- is a vectorized function. See ?"[<-" to get further details on that.
It depends on the type of your function. If f is vectorised then
V <- f(V) # V is a vector with random numbers
will do the job. If f takes and returns a single value then:
V <- sapply(V, f)
Thankfully, in R most of the function are vectorised, so the first approach would work quite often.

missing value where TRUE/FALSE needed error in R

I have got a column with different numbers (from 1 to tt) and would like to use looping to perform a count on the occurrence of these numbers in R.
count = matrix(ncol=1,nrow=tt) #creating an empty matrix
for (j in 1:tt)
{count[j] = 0} #initiate count at 0
for (j in 1:tt)
{
for (i in 1:N) #for each observation (1 to N)
{
if (column[i] == j)
{count[j] = count[j] + 1 }
}
}
Unfortunately I keep getting this error.
Error in if (column[i] == j) { :
missing value where TRUE/FALSE needed
So I tried:
for (i in 1:N) #from obs 1 to obs N
if (column[i] = 1) print("Test")
I basically got the same error.
Tried to do abit research on this kind of error and alot have to said about "debugging" which I'm not familiar with.
Hopefully someone can tell me what's happening here. Thanks!
As you progress with your learning of R, one feature you should be aware of is vectorisation. Many operations that (in C say) would have to be done in a loop, can be don all at once in R. This is particularly true when you have a vector/matrix/array and a scalar, and want to perform an operation between them.
Say you want to add 2 to the vector myvector. The C/C++ way to do it in R would be to use a loop:
for ( i in 1:length(myvector) )
myvector[i] = myvector[i] + 2
Since R has vectorisation, you can do the addition without a loop at all, that is, add a scalar to a vector:
myvector = myvector + 2
Vectorisation means the loop is done internally. This is much more efficient than writing the loop within R itself! (If you've ever done any Matlab or python/numpy it's much the same in this sense).
I know you're new to R so this is a bit confusing but just keep in mind that often loops can be eliminated in R.
With that in mind, let's look at your code:
The initialisation of count to 0 can be done at creation, so the first loop is unnecessary.
count = matrix(0,ncol=1,nrow=tt)
Secondly, because of vectorisation, you can compare a vector to a scalar.
So for your inner loop in i, instead of looping through column and doing if column[i]==j, you can do idx = (column==j). This returns a vector that is TRUE where column[i]==j and FALSE otherwise.
To find how many elements of column are equal to j, we just count how many TRUEs there are in idx. That is, we do sum(idx).
So your double-loop can be rewritten like so:
for ( j in 1:tt ) {
idx = (column == j)
count[j] = sum(idx) # no need to add
}
Now it's even possible to remove the outer loop in j by using the function sapply:
sapply( 1:tt, function(j) sum(column==j) )
The above line of code means: "for each j in 1:tt, return function(j)", an returns a vector where the j'th element is the result of the function.
So in summary, you can reduce your entire code to:
count = sapply( 1:tt, function(j) sum(column==j) )
(Although this doesn't explain your error, which I suspect is to do with the construction or class of your column).
I suggest to not use for loops, but use the count function from the plyr package. This function does exactly what you want in one line of code.

Resources