Column having maximum L2 norm - r

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

Related

Lapply over several parameters, faster method

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.

Flipping matrix columns

I have a matrix:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
I want to flip it so that the last column will be the firs and the first will be the last.
I know how to do it with a loop but is there any other quicker way to do this, e.g. with a function.
Here is the code that creates the matrix:
mat=matrix(c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20), ncol=5)
We can use reverse sequencing from last column index to the first one to do the flipping
mat[,ncol(mat):1]
It can be wrapped into a function
revflip <- function(matr) {
matr[, ncol(matr):1, drop = FALSE]
}
revflip(mat)

Indexing matrices when some elements of the selector are missing (R)

When some elements of a vector used for row-indexing a matrix or a data.frame are missing NA in R, the indexing operation has results that I find unexpected.
m = matrix(1:15,ncol = 3)
m[1,1] = NA
m[m[,1] < 4 ,]
Gives
[,1] [,2] [,3]
[1,] NA NA NA
[2,] 2 7 12
[3,] 3 8 13
While I would have expected
[,1] [,2] [,3]
[1,] NA 4 11
[2,] 2 7 12
[3,] 3 8 13
One option seems to be
m[m[,1] < 4 | is.na(m[,1]) ,]
But I find this unhandy. It often happens to me that I lose data by mistake when indexing matrices and data.frames that contains missings. Is there an easier and safer way to reach the desired result?

Writing a loop/function that compares adjacent columns in a matrix and picks the max value so to reduce the number of columns

I'm new to R and stuck. I want to reduce the number of columns in a 92x8192 matrix. The matrix consists of 92 observations and each column resembles a data point in a spectrum. The value corresponds to an intensity that is an integer. I want to reduce the "resolution" (i.e. the number of data points = columns) of the spectrum in a somewhat controlled way.
Example:
[,1] [,2] [,3] [,4] [,5] [,6] [...]
[1,] 1 2 3 4 5 6
[2,] 7 8 9 10 11 12
[3,] 13 14 15 16 17 18
[4,] 19 20 21 22 23 24
[5,] 25 26 27 28 29 30
[6,] 31 32 33 34 35 36
What i would like to do is compare adjacent columns (for each row) e.g [1,1] and [1,2], and find the max value of those two entries (that would be [1,2] in that case). The smaller value should be dropped, and the next two adjacent columns should be evaluated. So that in the end there will only be ncol/2 left. I know there is something like pmax. But since my knowledge with loops and functions is far too limited at this point i don't know how to not only compare two columns at a time but do it for all 4096 pairs of values in each row. In the end the matrix should look like this:
[,1] [,2] [,3] [...]
[1,] 2 4 6
[2,] 8 10 12
[3,] 14 16 18
[4,] 20 22 24
[5,] 26 28 30
[6,] 32 34 36
The values i have used are not a good example because i know that in this case it looks like i could just drop every other column and i know how to do that.
Apologies if the question is worded in a complicated way but i think the task isn't really all that complicated.
Thanks for any help or suggestions on how to go about this task.
Example matrix:
> set.seed(101)
> x_full <- matrix(runif(30), nrow=5)
> x_full
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0.37219838 0.3000548 0.8797957 0.59031973 0.7007115 0.79571976
[2,] 0.04382482 0.5848666 0.7068747 0.82043609 0.9568375 0.07121255
[3,] 0.70968402 0.3334671 0.7319726 0.22411848 0.2133520 0.38940777
[4,] 0.65769040 0.6220120 0.9316344 0.41166683 0.6610615 0.40645122
[5,] 0.24985572 0.5458286 0.4551206 0.03861056 0.9233189 0.65935508
Now reduce:
> x_reduced <- sapply(seq(1, ncol(x_full), 2), function(colnum) { pmax(x_full[, colnum], x_full[, colnum + 1]) })
> x_reduced
[,1] [,2] [,3]
[1,] 0.3721984 0.8797957 0.7957198
[2,] 0.5848666 0.8204361 0.9568375
[3,] 0.7096840 0.7319726 0.3894078
[4,] 0.6576904 0.9316344 0.6610615
[5,] 0.5458286 0.4551206 0.9233189
How it works: seq(1, ncol(x_full), 2) generates a sequence of integers representing the odd numbers up to the number of columns of x_full. Then sapply() applies a function to this sequence and presents the results in a tidy format (in this case it happens to be a matrix as we require). The function being applied is one that we specify using function: for column numbered colnum it just applies pmax() across that column and the next.
Example solution
mat = mat <- matrix(1:16,nrow=4)
m <- matrix(nrow=nrow(mat),ncol=ncol(mat)/2+1) #preassign a solution matrix to save time
for (i in seq(1,ncol(mat),2)){m[,i/2+1]<-(pmax(mat[,i],mat[,i+1]))}
your solution is then stored in m

R: How to convert a vector into matrix without replicating the vector?

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

Resources