I have a matrix
[,1] [,2]
[1,] 2 3
[2,] 3 5
[3,] 7 9
[4,] 11 3
[5,] 11 8
and I want to merge row 1 2 4 5 by their common value.
the result should be output
2 3 5 11 8
Test case:
m <- matrix(c(2,3,7,11,11,3,5,9,3,8),ncol=2)
I'm not sure this is what you want, but it gives the right answer:
unique(c(t(m[c(1,2,4,5),])))
Only two tricky bits here:
need to use c() to collapse the matrix into a single vector
need to use t() to get the matrix collapsed row-wise rather than column-wise to get the ordering as you specified.
Related
In R, I have a matrix of...
data1 <- c(9,8,7,6,5,4,3,2,1,10,11,12,13,14,15)
matrix_1 <- matrix(data1,nrow=5,ncol=3,byrow=T)
Now that should create the matrix
[,1] [,2] [,3]
[1,] 9 8 7
[2,] 6 5 4
[3,] 3 2 1
[4,] 10 11 12
[5,] 13 14 15
My goal is to create a 6x4 matrix with that exact matrix for the first 5 rows and 3 columns, then the remaining row and column are sums of the respective row or column, then the single extra spot in the bottom right corner is the total sum of the entire first matrix (matrix_1).
I assume I need to use for loops, but I can't figure out how to get it. Thanks.
I tried messing with the for loop a bit, but I'm stuck on what to sum for that second matrix as well as how to cut the loop at the right point.
Base R has the addmargins() convenience function for this. The default returns the sum of all margins of a matrix or array.
addmargins(matrix_1)
Sum
9 8 7 24
6 5 4 15
3 2 1 6
10 11 12 33
13 14 15 42
Sum 41 40 39 120
R has an apply family (apply, sapply, lapply etc.) that allows you to do stuff without using a for loop.
Here, row sum and column sum are calculated using apply, where 1 in apply(matrix_1, 1, sum) specifies row-wise operation, and 2 specifies column-wise operation. Then rbind and cbind the results to output a 6 x 4 matrix.
rbind(
cbind(matrix_1, apply(matrix_1, 1, sum)),
c(apply(matrix_1, 2, sum), sum(matrix_1))
)
However, in your case, you don't really need to use apply. You can use rowSums and colSums in base R to do the job.
rbind(
cbind(matrix_1, rowSums(matrix_1)),
c(colSums(matrix_1), sum(matrix_1))
)
Output
[,1] [,2] [,3] [,4]
[1,] 9 8 7 24
[2,] 6 5 4 15
[3,] 3 2 1 6
[4,] 10 11 12 33
[5,] 13 14 15 42
[6,] 41 40 39 120
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
I want to use sapply to create a 2 columns matrix, 8 rows. First column is from 1 to 8 and second column is the square of the first. I did sapply(1:8, function(x), c(x,x^2)) so I got 8 columns and 2 rows instead of getting 2 columns and 8 rows. How can I replace columns by rows?
Try using t
> t(sapply(1:8, function(x) c(x,x^2)))
[,1] [,2]
[1,] 1 1
[2,] 2 4
[3,] 3 9
[4,] 4 16
[5,] 5 25
[6,] 6 36
[7,] 7 49
[8,] 8 64
Actually no need to use sapply for that, just use matrix
> x <- 1:8
> matrix(c(x,x^2), ncol=2)
The default for sapply is to essentially cbind the the final output. You can either tell it to not simplify or just transpose your result.
# manual rbind
do.call("rbind", sapply(1:8, function(x) c(x,x^2), simplify=FALSE))
# transpose result
t(sapply(1:8, function(x) c(x,x^2)))
I am trying to cut one row
x = [1 2 3 4 5 6 7 8 9 10 11 12]
into multiple rows of equal length so that
y(row1) = [1 2 3 4
y(row2) = 5 6 7 8
y(row3) = 9 10 11 12]
I know I can achieve this using a combination of rbind and cbind, but the dataset I am trying to apply this to is much larger than the example, so I am looking for a way to do it more quickly and automatically. I tried cut and cut2 but those didnt work either
jelle
The function matrix() is your friend here:
> matrix(1:12, nrow = 3, byrow = TRUE)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
Note the optional parameter, byrow. The default is FALSE and will fill the matrix by columns, setting it to true in this case gets the data arranged in the order that you described.Just something to be careful about, since R won't throw an error if you fill by column, but your data won't be in the right format!
Use matrix:
> y <- 1:12
> y
[1] 1 2 3 4 5 6 7 8 9 10 11 12
> matrix(y,3,4,byrow=1)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
Edit: I included the byrow=TRUE argument to matrix (pointed out by Chase in the comments) which fills the matrix along the rows instead of down the columns.
I have two matrices I want to perform a loop on. My problem is I am looping for one colomn and do not know how to include the other column, hence my incorrect results. My codes are as below:
t=as.matrix(b)
y=as.matrix(a)
t
a b
[1,] 1 10
[2,] NA 9
[3,] 3 NA
[4,] 4 7
[5,] 5 6
[6,] 3 4
y
c d
[1,] 3 12
[2,] NA 11
[3,] 5 NA
[4,] 6 9
[5,] 7 8
[6,] 3 12
turn
[,1] [,2]
[1,] 0 0
[2,] 0 0
Code:
n=3 #number to consider at a time
runs=2 #total data points divided by 60 to the nearest whole number
turn=matrix(0, nrow=runs,2)
TR = y/t
for (i in 1: runs){
index_start=3*(i-1)+1
index_end= 3*i
turn[i]=mean( TR[index_start:index_end],na.rm=TRUE)
}
turn
[,1] [,2]
[1,] 2.333333 0
[2,] 1.300000 0
The turn output has given correct results for the first column but, as expected, incorrect results for the second column. How do I adjust my loop function? Thank you in advance.
Look at the line
turn[i]=mean( TR[index_start:index_end],na.rm=TRUE)
If you only give a single number in the index of a matrix, it will work out the position by counting down the first column, then down the second, and so on.
So turn[1] refers to the element in the top left corner of the matrix turn, and turn[2] refers to the bottom left corner.
In your loop, i takes the values 1:runs, and runs is 2, so you only assign things to the first two elements of turn.