Extracting Every Nth Element of A Matrix - r

I want to extract every nth element of row for each row in a matrix, here is my code:
x <- matrix(1:16,nrow=2)
x
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 3 5 7 9 11 13 15
[2,] 2 4 6 8 10 12 14 16
I have tried:
sapply(x, function(l) x[seq(1,8,2)])
which clearly fails.
I want to pull every 2nd value from "x" the desired output would be something like...
[,1] [,2] [,3] [,4]
[1,] 3 7 11 15
[2,] 4 8 12 16

You are overcomplicating it:
This gives you what you need
x[,seq(2, 8, 2)]
or, more generally
x[,seq(2, ncol(x), 2)]

Related

Recycle vector by starting from the end

I'm trying to recycle a vector, but don't want to recycle with the default in R.
Imagine I have 2 vectors with unequal number of elements:
gen1 = 2:10
gen2 = 1:10
rbind(gen1,gen2)
This gives this table
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
gen1 2 3 4 5 6 7 8 9 10 2
gen2 1 2 3 4 5 6 7 8 9 10
As you can see in the last column, the 2 gets paired with 10. But I want this:
gen1 = c(2,2:10)
gen2 = 1:10
rbind(gen1,gen2)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
gen1 2 2 3 4 5 6 7 8 9 10
gen2 1 2 3 4 5 6 7 8 9 10
Now the 2 is duplicated, but at the front. Evidently I do not want to do this by hand since I have a collection of these non pairing vectors which I want to use this trick. Is there a way to do this?
Or perhaps a way to find the 'closest' position possible in the list.
For example, if I have
[,1] [,2] [,3] [,4] [,5] [,6]
gen1 8 9 10 8 9 10
gen2 5 6 7 8 9 10
I would like this to be:
[,1] [,2] [,3] [,4] [,5] [,6]
gen1 8 8 9 9 10 10
gen2 5 6 7 8 9 10
First example in question
1) Convert each to a ts series with appropriate alignment and then use na.locf.
library(zoo)
# inputs
gen1 <- 2:10; gen2 = 1:10
t(na.locf(cbind(gen1 = ts(gen1, start = 2), gen2 = ts(gen2)), fromLast = TRUE))
giving:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
gen1 2 2 3 4 5 6 7 8 9 10
gen2 1 2 3 4 5 6 7 8 9 10
2) It can also be written with pipes like this
cbind(gen1 = ts(gen1, start = 2), gen2 = ts(gen2)) |>
na.locf(fromLast = TRUE) |>
t()
3) If you want to derive the aligment from the data itself use this:
maxlen <- max(length(gen1), length(gen2))
cbind(gen1 = ts(gen1, end = maxlen), gen2 = ts(gen2, end = maxlen)) |>
na.locf(fromLast = TRUE) |>
t()
4) Another approach is to use dynamic time warping.
library(dtw)
with(dtw(gen1, gen2), rbind(gen1 = gen1[index1], gen2 = gen2[index2]))
giving:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
gen1 2 2 3 4 5 6 7 8 9 10
gen2 1 2 3 4 5 6 7 8 9 10
Last example in question
The last example in the question seems entirely different and is just a matter of sorting each row.
# input in reproducible form
m <- rbind(gen1 = c(8, 9, 10, 8, 9, 10), gen2 = c(5, 6, 7, 8, 9, 10))
t(apply(m, 1, sort))
giving
[,1] [,2] [,3] [,4] [,5] [,6]
gen1 8 8 9 9 10 10
gen2 5 6 7 8 9 10
I think this is the trick:
gen1 = c(2,2:10)
gen2 = 1:10
ddd=rbind(gen1,gen2)
ddd[1,] = sort(ddd[1,])
ddd
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
gen1 2 2 3 4 5 6 7 8 9 10
gen2 1 2 3 4 5 6 7 8 9 10

how to perform a combination procedure on a vector such that i have the original vector as the first row

I have this vector
b=c(5,8,9)
I want to perform a combination on b selecting 2 items at a time such that i have the original elements of b as my first row to get
[,1] [,2] [,3]
[1,] 5 8 9
[2,] 8 9 5
I tried combn(b, 2) and it gives me this
[,1] [,2] [,3]
[1,] 5 5 8
[2,] 8 9 9
Can i get help to achieve my desired result?
Since the second row of your desired result is not uniquely defined, there is no need for any sophisticated tools:
b <- 1:10
rbind(b, c(b[-1], b[1]))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# b 1 2 3 4 5 6 7 8 9 10
# 2 3 4 5 6 7 8 9 10 1
In this case I only "shift" b by one position in the second row, which indeed results in a permutation. I'm assuming that the elements of b don't repeat.

How to concatenate column repetitions of a matrix without a for loop

Let's say I have the below matrix:
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
I want to generate a matrix which is the concatenation (by column) of matrices that are generated by repetition of each column k times. For example, when k=3, below is what I want to get:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 2 2 2
[2,] 3 3 3 4 4 4
[3,] 5 5 5 6 6 6
How can I do that without a for loop?
You can do this with column indexing. A convenient way to repeat each column number the correct number of times is the rep function:
mat[,rep(seq_len(ncol(mat)), each=3)]
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 1 1 1 2 2 2
# [2,] 3 3 3 4 4 4
# [3,] 5 5 5 6 6 6
In the above expression, seq_len(ncol(mat)) is the sequence from 1 through the number of columns in the matrix (you could think of it like 1:ncol(mat), except it deals nicely with some special cases like 0-column matrices).
Data:
(mat <- matrix(1:6, nrow=3, byrow = TRUE))
# [,1] [,2]
# [1,] 1 2
# [2,] 3 4
# [3,] 5 6
We can repeat each element of matrix k times and fit the vector in a matrix where number of columns is k times the original one.
k <- 3
matrix(rep(t(mat), each = k), ncol = ncol(mat) * k, byrow = TRUE)
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 1 1 1 2 2 2
#[2,] 3 3 3 4 4 4
#[3,] 5 5 5 6 6 6

Create new columns based on rows

If I had a matrix like:
[,1] [,2]
[1,] 1 7
[2,] 2 8
[3,] 3 9
[4,] 4 10
[5,] 5 11
[6,] 6 12
Does anyone have an idea as to how I might create a new matrix from the above that looks like:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 7 3 9 5 11
[2,] 2 8 4 10 6 12
We create a grouping variable with ?gl and use the arguments n=nrow(m1), k=2 and length=nrow(m1). We split the matrix ('m1'), unlist, and create a new matrix with nrow=2.
matrix(unlist(split(m1,as.numeric(gl(nrow(m1), 2, nrow(m1))))),nrow=2)
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 1 7 3 9 5 11
#[2,] 2 8 4 10 6 12
Or another option is converting to array by specifying the dimensions. Here I used c(2, 2, 3) as we can get a 2x2 matrix for the first two dimensions and the third is based on the nrow(m1)/2. Then, we can permute the dimensions of the array using aperm, concatenate (c) to form a vector and convert to matrix.
matrix(c(aperm(array(t(m1), c(2, 2,3)),c(2,1,3))), nrow=2)
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 1 7 3 9 5 11
#[2,] 2 8 4 10 6 12
data
m1 <- structure(1:12, .Dim = c(6L, 2L))
Here' another option: First the matrix is transformed into one with two rows, then the odd and even numbered columns are rearranged:
m3 <- m2 <- matrix(c(m),nrow = 2) #take data from original matrix, convert it into a matrix with two rows and store a copy in m2 and m3
m3[,seq(1,ncol(m2),2)] <- m2[,1:(ncol(m2)/2)] #define the odd-numbered columns of m3
m3[,seq(2,ncol(m2),2)] <- m2[,(ncol(m2)/2+1):ncol(m2)] # same for the even-numbered columns
> m3
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 1 7 3 9 5 11
#[2,] 2 8 4 10 6 12

Pairwise calculation in r

I have been thinking about a problem I have but I don't know how to express the problem to even search for it. I'd be very thankful if you could explain it to me.
So, I have a data set with the following format:
10 6 4 4
10 6 4 4
7 6 4 4
I want to conduct a pairwise calculation for which I need to sum each element to the other one by one. That is 1 with 2, 1 with 3, 1 with 4, 2 with 3, 2 with 4 and 3 with 4.
I thought to do a nested a loop in R which I read about it and I started like this:
for (i in 1:r-1) { ## r the number of columns
for (j in (i+1):r) {
....
}
I am stuck at this stage, I don't know how to express in codes what I need to do. I am sorry for posting a not progressed code, some advice would be very good that how I should go about it.
Thanks a lot in advance.
Use combn to create the "pairs":
(pairs <- combn(4,2))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 2 2 3
[2,] 2 3 4 3 4 4
Then apply across the rows of your data by summing these subsets by applying across the columns of the pairs:
dat <- matrix(c(10,10,7,6,6,6,4,4,4,4,4,4),ncol=4)
t(apply(dat, 1, function(x) apply(combn(4,2),2,function(y) sum(x[y]))))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 16 14 14 10 10 8
[2,] 16 14 14 10 10 8
[3,] 13 11 11 10 10 8
You could slightly modify your loop:
d <- read.table(text='
10 6 4 4
10 6 4 4
7 6 4 4')
nc <- ncol(d)
r <- NULL
for (i in 1:nc) {
for (j in 1:nc) {
if (i < j) { # crucial condition
r <- cbind(r, d[, i] + d[, j]) # calculate new column and bind to calculated ones
}
}
}
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 16 14 14 10 10 8
[2,] 16 14 14 10 10 8
[3,] 13 11 11 10 10 8
Another application of combn but perhaps easier to understand:
apply(combn(ncol(dat),2), 2, function(x) rowSums(dat[,x]))
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 16 14 14 10 10 8
## [2,] 16 14 14 10 10 8
## [3,] 13 11 11 10 10 8
Here, the matrix dat is indexed by each column of the result of combn giving a matrix of two columns (the two columns to be summed). rowSums then does the arithmetic.
Because I really like package functional, here is a slight variation on the above:
apply(combn(ncol(dat),2), 2, Compose(Curry(`[`, dat, i=seq(nrow(dat))), rowSums))
It should be noted that a combn approach is more flexible than using nested for loops for this sort of computation. In particular, it is easily adapted to any number of columns to sum:
f <- function(dat, num=2)
{
apply(combn(ncol(dat),num), 2, function(x) rowSums(dat[,x,drop=FALSE]))
}
This will give all combinations of num columns, and sum them:
f(dat, 1)
## [,1] [,2] [,3] [,4]
## [1,] 10 6 4 4
## [2,] 10 6 4 4
## [3,] 7 6 4 4
f(dat, 2)
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 16 14 14 10 10 8
## [2,] 16 14 14 10 10 8
## [3,] 13 11 11 10 10 8
f(dat, 3)
## [,1] [,2] [,3] [,4]
## [1,] 20 20 18 14
## [2,] 20 20 18 14
## [3,] 17 17 15 14
f(dat, 4)
## [,1]
## [1,] 24
## [2,] 24
## [3,] 21

Resources