> fun1 <- function(x,y){x+y}
> outer(seq(1,5,length=5),seq(6,10,length=5),fun1)
[,1] [,2] [,3] [,4] [,5]
[1,] 7 8 9 10 11
[2,] 8 9 10 11 12
[3,] 9 10 11 12 13
[4,] 10 11 12 13 14
[5,] 11 12 13 14 15
> fun2 <- function(x,y){z<-c(x,y);z[1]+z[2]}
> outer(seq(1,5,length=5),seq(6,10,length=5),fun2)
Error in dim(robj) <- c(dX, dY) :
dims [product 25] do not match the length of object [1]
Why doesn't fun2() work? Aren't fun2() and fun1() essentially the same thing?
As an alternative, you can just replace fun2 with Vectorize(fun2) when passing it as argument to outer:
fun2 <- function(x,y){z<-c(x,y);z[1]+z[2]}
outer(seq(1,5,length=5),seq(6,10,length=5), Vectorize(fun2))
The answer becomes obvious if you read ?outer:
Details:
‘X’ and ‘Y’ must be suitable arguments for ‘FUN’. Each will be
extended by ‘rep’ to length the products of the lengths of ‘X’ and
‘Y’ before ‘FUN’ is called.
‘FUN’ is called with these two extended vectors as arguments.
Therefore, it must be a vectorized function (or the name of one),
expecting at least two arguments.
Think about what you are doing, you are concatenating two vectors into one vector, then sum the first and second elements of this vector. fun1() on the other hand does the vectorised sum of the inputs, so the returned object is of the same length as the individual lengths of the inputs. In fun2(), the output is a vector of length 1 and it was expecting 25.
The way to make the idea behind fun2() work is to cbind() not c() the two inputs:
> fun3 <- function(x, y) { z <- cbind(x, y); z[,1] + z[,2]}
> outer(seq(1,5,length=5),seq(6,10,length=5),fun3)
[,1] [,2] [,3] [,4] [,5]
[1,] 7 8 9 10 11
[2,] 8 9 10 11 12
[3,] 9 10 11 12 13
[4,] 10 11 12 13 14
[5,] 11 12 13 14 15
Related
How to find the column of a matrix which has the maximum L2 norm? The matrix has NA values in some columns, we want to ignore those columns.
The following code I am trying, but it shows error due to NA values.
#The matrix is T
for(i in 1:ncol(T)){
if(norm(y,type='2') < norm(T[,i],type = '2'))
y = T[,i]
}
I think it would also be useful if we could somehow get the columns of T as a list, since we could use which.max function then, but I could not do that. Is that possible?
Please help
Maybe you can write your own L2 norm and find the column with the maximum, i.e.,
which.max(sqrt(colSums(T**2)))
Example
T <- matrix(c(1:10,NA,12:19,NA),nrow = 4)
> T
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 NA 15 19
[4,] 4 8 12 16 NA
> which.max(sqrt(colSums(T**2)))
[1] 4
Suppose I have two vectors
a <- c(1,2,3,4,5)
b <- c(6,7,8,9,10)
and a function
calc <- function(x,y){x + y)
I want to apply this function for the 1st value in a for each value in b. Suppose in my case calc only allows a single value from a and b as input, so lapply(a,calc,b) wouldn't work because the length(b) is not 1 then (gives me an error).
Also mapply doesnt give me the wanted solution either, it only applies the function on paired values, i.e. 1+6, 2+7, etc.
So I built a function that gave me the wanted solution
myfunc <- function(z){lapply(a,calc,z)}
and applied it on b
solution <- lapply(b,myfunc)
We see here that the difference to lapply(a,calc,b) or a nested lapply(a,lapply,calc,b) is that it gives me all the values in its own list. Thats what I wanted or at least it was a function that gave me the right result with no error.
Now, is there a faster/ more trivial method, because I just experimented here a little. And with my function which is much larger than calc it takes 10 minutes, but maybe I have to slim down my original function and there would not be a faster method here...
EDIT:
In my function there is something like this,
calc <- function(x,y){
# ...
number <- x
example <- head(number,n=y)
# ...
}
where a vector as an input for y doesnt work anymore. With lapply(a,lapply,calc,b) or lapply(a,calc,b) I get an error,
Error in head.default(number, n = y) : length(n) == 1L is not TRUE
As Florian says, outer() could be an option.
outer(a, b, calc)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 7 8 9 10 11
# [2,] 8 9 10 11 12
# [3,] 9 10 11 12 13
# [4,] 10 11 12 13 14
# [5,] 11 12 13 14 15
But as MichaelChirico mentions, with a function that isn't vectorized it won't work. In that case something else has to be hacked together. These might or might not be quicker than your current solution.
All combinations (so both calc(1, 6) and calc(6, 1) are performed, similar to outer()
Number of calculations: n2
eg <- expand.grid(a, b)
m1 <- mapply(calc, eg[,1], eg[, 2])
matrix(m1, 5)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 7 8 9 10 11
# [2,] 8 9 10 11 12
# [3,] 9 10 11 12 13
# [4,] 10 11 12 13 14
# [5,] 11 12 13 14 15
Only unique combinations (so assumes your function is symmetric)
Number of calculations: (n2 - n) / 2
cn <- t(combn(1:length(a), 2))
m2 <- mapply(calc, a[cn[, 1]], b[cn[, 2]])
mat <- matrix(, length(a), length(a))
mat[upper.tri(mat)] <- m2
mat
# [,1] [,2] [,3] [,4] [,5]
# [1,] NA 8 9 10 11
# [2,] NA NA 10 11 12
# [3,] NA NA NA 12 13
# [4,] NA NA NA NA 14
# [5,] NA NA NA NA NA
This second one ignores the diagonal, but adding those values are easy, as that's what the OPs mapply() call returned.
diag(mat) <- mapply(calc, a, b)
mat
# [,1] [,2] [,3] [,4] [,5]
# [1,] 7 8 9 10 11
# [2,] NA 9 10 11 12
# [3,] NA NA 11 12 13
# [4,] NA NA NA 13 14
# [5,] NA NA NA NA 15
This solved it for me, adding SIMPLIFY=FALSE to the mapply function, thanks to #AkselA.
eg <- expand.grid(a, b)
m1 <- mapply(calc, eg[,1], eg[, 2],SIMPLIFY=FALSE)
However, this method is only slightly faster than my own solution in my OP.
Here's my problem:
I have a vector and I want to convert it into a matrix with fixed number of columns, but I don't want to replicate the vector to fill the matrix when it's necessary.
For example:
My vector has a length of 15, and I want a matrix with 4 columns.I wish to get the matrix wit 15 elements from the vector and a 0 for the last element in the matrix.
How can I do this?
Edit:
Sorry for not stating the question clearly and misguiding you guys with my example. In my program,I don't know the length of my vector, it depends on other parameters and this question involves with a loop, so I need a general solution that can solve many different cases, not just my example.
Thanks for answering.
You could subset your vector to a multiple of the number of columns (so as to include all the elements). This will add necessary amount of NA to the vector. Then convert to matrix.
x = 1:15
matrix(x[1:(4 * ceiling(length(x)/4))], ncol = 4)
# [,1] [,2] [,3] [,4]
#[1,] 1 5 9 13
#[2,] 2 6 10 14
#[3,] 3 7 11 15
#[4,] 4 8 12 NA
If you want to replace NA with 0, you can do so using is.na() in another step
We can also do this with dim<- and length<-
n <- 4
n1 <- ceiling(length(x)/n)
`dim<-`(`length<-`(x, n*n1), c(n1, n))
# [,1] [,2] [,3] [,4]
#[1,] 1 5 9 13
#[2,] 2 6 10 14
#[3,] 3 7 11 15
#[4,] 4 8 12 NA
data
x <- 1:15
This question already has answers here:
Mean of each element of a list of matrices
(3 answers)
Closed 6 years ago.
I have a list of matrices:
.list <- list(matrix(1:25, ncol = 5), matrix(11:35, ncol = 5))
I would like to use the Reduce method to find the element-by-element means of the matrices in the list.
In other words, I am looking for the following result:
res = matrix(6:30, ncol = 5)
I tried the following:
res = Reduce(mean, .list)
but I get an error:
Error in mean.default(init, x[[i]]) :
'trim' must be numeric of length one
Note that an element of a matrix can be NA.
Any help would be appreciated! Thank you!!
I just realized that this could be achieved the following way (using the Reduce function):
tmp = Reduce('+', .list)
result = tmp/length(.list)
This is probably easier to solve via an array, rather than a list, as R has some inbuilt, vectorised approaches to this problem.
To get an array from .list, unlist it and supply the relevant dimensions (which could be automated by looking up the dim() of .list[[1]] and length(.list):
arr <- array(unlist(.list), dim = c(5,5,2))
Then, the desired result is obtained via rowMeans() (yes, really!)
rowMeans(arr, dim = 2)
R> rowMeans(arr, dim = 2)
[,1] [,2] [,3] [,4] [,5]
[1,] 6 11 16 21 26
[2,] 7 12 17 22 27
[3,] 8 13 18 23 28
[4,] 9 14 19 24 29
[5,] 10 15 20 25 30
The na.rm argument handles the NA case too:
R> rowMeans(arr, dim = 2, na.rm = TRUE)
[,1] [,2] [,3] [,4] [,5]
[1,] 6 11 16 21 26
[2,] 7 12 17 22 27
[3,] 8 13 18 23 28
[4,] 9 14 19 24 29
[5,] 10 15 20 25 30
A slower way is to use apply(), which may be more instructive as to what rowMeans() is doing:
R> apply(arr, 1:2, mean, na.rm = TRUE)
[,1] [,2] [,3] [,4] [,5]
[1,] 6 11 16 21 26
[2,] 7 12 17 22 27
[3,] 8 13 18 23 28
[4,] 9 14 19 24 29
[5,] 10 15 20 25 30
i.e applying the mean function, grouping the data by the row and column dimensions. Think of the array as a box, with the height of the box being the third dimension. This box consists of little cubes, like a rubic cube. We want the mean of the little cubes stacked up above each row and column combination; the mean of the little cubes stacked above (1,1), and so on. This is what the apply() and rowMeans() functions do for you, if you treat the multiple matrices in a list as an array.
Here is one way with mapply.
matrix(do.call(mapply, c(function(...) mean(unlist(list(...))), .list)), ncol=5)
As a side note, .list isn't the best way to use a keyword as a variable name. In R, the period prefix means something like "meta-variable", and these variables won't show up when you call ls(). You could do list. or the easier to read list_.
This is a really basic question, but I can't seem to solve it or find an answer for it anywhere : suppose I have two vectors x,y of coordinates and a matrix m.
I would like a vector z such that z[i] = m[x[i],y[i]]for all i.
I tried z=m[x,y], but that creates a memory overflow. The vector and matrix are quite large so looping is pretty much out of the question. Any ideas ?
Use cbind. Here's a simple example:
mat <- matrix(1:25, ncol = 5)
mat
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 6 11 16 21
# [2,] 2 7 12 17 22
# [3,] 3 8 13 18 23
# [4,] 4 9 14 19 24
# [5,] 5 10 15 20 25
x <- 1:5
y <- c(2, 3, 1, 4, 3)
mat[cbind(x, y)]
# [1] 6 12 3 19 15
## Verify with a few values...
mat[1, 2]
# [1] 6
mat[2, 3]
# [1] 12
mat[3, 1]
# [1] 3
From ?Extract:
A third form of indexing is via a numeric matrix with the one column for each dimension: each row of the index matrix then selects a single element of the array, and the result is a vector. Negative indices are not allowed in the index matrix. NA and zero values are allowed: rows of an index matrix containing a zero are ignored, whereas rows containing an NA produce an NA in the result.
Another way is to use the fact that you can index a matrix as if it were a vector, with elements numbered in column-major form. Using the example from #AnandoMahto:
mat[x+nrow(mat)*(y-1)]
[1] 6 12 3 19 15