R has the function outer that allows you to compute a function for every combination of inputs xs and ys, e.g.:
xs <- 1:5
ys <- 0:10
zs <- outer(xs, ys, Vectorize(function(x, y) sin(x) + y**2))
Let's say I want to know the minimal value in zs:
> min(zs)
[1] -0.9589243
and what position it's in:
> which(zs==min(zs))
[1] 5
Now how can I figure out which x of xs and which y of ys produced the 5th z of zs?
I can recompute using something like outer(xs, ys, Vectorize(function(x, y) paste(x,y)))[which(zs==min(zs))] to get a string of the indices, but this seems bloody inefficient to me. What's a better way?
You have to use:
which(zs==min(zs), arr.ind=T)
# row col
#[1,] 5 1
You can use arr.index=TRUE
which(zs==min(zs),arr.ind = TRUE)
One can use expand.grid:
> expand.grid(xs, ys)[zs==min(zs),]
Var1 Var2
5 5 0
Related
I want to write a loop, in which values from 3 different lists are put into another function
x = list(value1, value2, value3)
y = list(value1, value2, value3)
z = list(value1, value2, value3)
Example: function (x1, y1, z1)
I want to insert the values from the same column(x1, y1, z1 .... x3, y3, z3)of the different lists into the function. How could I do that?
This could be achieved using e.g. mapply:
x <- list(1, 2, 3)
y <- list(4, 5, 6)
z <- list(7, 8, 9)
mapply(function(vx, vy, vz) vx + vy + vz, x, y, z)
#> [1] 12 15 18
or using purrr::pmap:
purrr::pmap(list(x, y, z), function(vx, vy, vz) vx + vy + vz)
You get value1 from x list by using x[[1]]. Likewise, you get velue3 from y list by using y[[3]], etc.
You can then use these values in your function in various ways, depending on what your function has to do with these values.
#stefan has shown two efficient ways to do that.
If your function has to take three values from the same indices to result in a single value, such as mean, you can combine the list to become a matrix with three columns and three rows, so that you can apply this function to each column or each row with single index.
x = list(c(-3,0,2))
y = list(c(10,-1,20))
z = list(c(0.7, 0.5, 0.9))
myData = cbind(x,y,z)
myData
# x y z
# [1,] -3 10 0.7
# [2,] 0 -1 0.5
# [3,] 2 20 0.9
To get the mean of the value1s :
mean(myData[1,])
# [1] 2.566667
Suppose you want to compute the means and the standard deviations of each row, you can write a function to do that
myfun = function(x){
Mean = apply(x, 1, mean)
SD = apply(x, 1, sd)
result = rbind(Mean, SD)
return(result)
}
and then apply the function to your matrix:
myfun(myData)
# [,1] [,2] [,3]
# Mean 2.566667 -0.1666667 7.633333
# SD 6.698010 0.7637626 10.723961
This is just an example. Many other, more efficient, ways are possible.
I have to compute a product of 3 matrices D=ABC with:
A is a (1x3) matrix,
B is a (3x3) matrix,
C is a (3x1) matrix (and is equal to A', if it matters)
The result of this product is a simple value, and the calculation is very straightforward in R.
My problem is there is one unknown, namely X, inside A and C, and I would like to get the result as a formula: D = ABD = f(X).
Is there any way I could achieve this with R ?
Define D as shown below where argument B is the square matrix and A is a function of x returning a vector.
D <- function(B, A) function(x) t(A(x)) %*% B %*% A(x)
# test
A <- function(x) seq(3) * x
B <- matrix(1:9, 3)
Dfun <- D(B, A)
Dfun(10)
## [1] 22800
I am new to R environment and would like the understand the code posted in another thread.
Integrating over a PCHIP Function
1 > library(pracma)
2 > xs <- linspace(0, pi, 10)
3 > ys <- sin(xs)
4 > pchipfun <- function(xi, yi) function(x) pchip(xi, yi, x)
5 > f <- pchipfun(xs, ys)
6 > integrate(f, 0, pi)
My questions are as follows:
Line 5 is calling function in line 4, but this is not passing x value. So how does line 4 take x value?
In the above setup, I would like to modify such that if x is in between pi/6 & pi/4, the function should return 0 otherwise return calculated value.
Thanks in advance.
For question 1, you can read about Currying:
https://en.wikipedia.org/wiki/Currying
For question 2, perhaps you can paste what you have tried first.
Assuming that I have a function, let's say f(x).
How can I write the product or sum of this function for given limits in x.
For instance product of f for x=1 until x=5
f(1)*f(2)*f(3)*f(4)*f(5)
Additionally I need to figure this out for sums/double sums.
Consider f(x,y) and the sum while x runs from 1 to 3 and y runs from 0 to x-1.
If written in mathematica, it would be this:
Sum[f[x, y], {x, 1, 3}, {y, 0, x - 1}]
and the output would be this
f[1, 0] + f[2, 0] + f[2, 1] + f[3, 0] + f[3, 1] + f[3, 2]
f is not defined for simplicity.
EDIT: example as requested:
f <- function (x,y) {
x + 2*y
}
Calculate sum where x runs from 1 to 3 and y runs from 0 to x-1.
(this is equal to 22 btw)
You can do this:
f <- function (x,y) {
x + 2*y
}
)
#calculate f for all combinations
tmp <- outer(1:3, 0:2, f)
#discard undesired combinations and sum
sum(tmp[lower.tri(tmp, diag = TRUE)])
#[1] 22
Alternatively you can use a loop to create the desired combinations only. This is much slower:
inds <- lapply(1:3, function(x) data.frame(x = x, y = 0:(x-1)))
inds <- do.call(rbind, inds)
sum(do.call(f, inds))
#[1] 22
I have a function in R that takes in 3 parameters, say foo(x,y,z).
When I call the function, I really have a list of elements for x, and a list for y but only one element for z. If Z was a list, and I wanted to apply foo to each element, mapply(foo, x, y, z) works.
However, since z is not a list, mapply(foo,x,y,z) does not work.
More specifically, if x and y are lists of 3 elements each, the following does work however: mapply(foo, x, y, list(z, z, z)).
Is there a way I can perhaps combine mapply and sapply without me first making z into a list of 3 elements? I want z to just be reused!
Edit 1: I was asked for an example:
mylist1 <- list(c(5,4), c(7,9), c(8,3))
mylist2<- list(c(2,3), c(6,7), c(10,11))
item3 <- matrix(data = 15, nrow = 3, ncol = 3)
foo <- function(x,y,z){
return(x[1]+y[2]+z[2,2])
}
The following works:
> mapply(foo, mylist1, mylist2, list(item3,item3, item3))
[1] 23 29 34
The following does not work:
mapply(foo, mylist1, mylist2, item3)
Error in z[2, 2] : incorrect number of dimensions
Use the MoreArgs argument to mapply
mapply(foo, x = mylist1, y= mylist2, MoreArgs = list(z = item3))
## [1] 23 29 34
You just have to put the last item in a list, and R will recycle it just fine:
mapply(foo, mylist1, mylist2, list(item3))
Note that the documentation specifically says that the arguments you pass need to be:
arguments to vectorize over (vectors or lists of strictly positive length, or all of zero length)
and you were trying to pass a matrix.