Get all combination of treatment & control in R [duplicate] - r

This question already has answers here:
Create combinations of a binary vector
(6 answers)
Closed 1 year ago.
I am using the combn function in R to find the combinations of treatment and control in R, however this function doesn't account for order.
Is there another function similar to combn that could account for combination in different orders?
I hope to achieve this in the end
i.e.
000111
001110
011100
....
(should have 20 combination of 6 choose 3)

Try the code below
> t(combn(6, 3, function(k) replace(rep(0, 6), k, 1)))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 0 0 0
[2,] 1 1 0 1 0 0
[3,] 1 1 0 0 1 0
[4,] 1 1 0 0 0 1
[5,] 1 0 1 1 0 0
[6,] 1 0 1 0 1 0
[7,] 1 0 1 0 0 1
[8,] 1 0 0 1 1 0
[9,] 1 0 0 1 0 1
[10,] 1 0 0 0 1 1
[11,] 0 1 1 1 0 0
[12,] 0 1 1 0 1 0
[13,] 0 1 1 0 0 1
[14,] 0 1 0 1 1 0
[15,] 0 1 0 1 0 1
[16,] 0 1 0 0 1 1
[17,] 0 0 1 1 1 0
[18,] 0 0 1 1 0 1
[19,] 0 0 1 0 1 1
[20,] 0 0 0 1 1 1

Related

Find number of neighbouring values in a matrice (R)

My matrice is like this:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 0 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 1 1
[5,] 0 0 0 0 0 0 1 1 0
[6,] 0 0 0 0 0 1 0 0 0
[7,] 0 0 0 0 1 1 0 0 0
[8,] 0 0 0 0 1 0 0 0 0
[9,] 0 0 0 0 1 0 0 0 0
[10,] 0 0 0 0 1 1 0 0 0
[11,] 0 0 0 0 0 1 0 0 0
[12,] 0 0 0 0 0 1 1 1 1
[13,] 0 0 0 0 0 0 0 0 0
[14,] 0 0 0 0 0 0 0 0 0
[15,] 0 0 0 0 0 0 0 0 0
[16,] 0 0 0 0 0 0 0 0 0
[17,] 0 0 0 0 0 0 0 0 0
[,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17]
[1,] 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0
[4,] 1 1 0 0 0 0 0 0
[5,] 0 1 0 0 0 0 0 0
[6,] 0 1 0 0 0 0 0 0
[7,] 0 1 0 0 0 0 0 0
[8,] 0 1 0 0 0 1 0 0
[9,] 0 1 0 0 0 1 0 0
[10,] 1 1 0 0 0 1 0 0
[11,] 1 1 0 1 1 0 0 0
[12,] 1 1 1 1 0 0 0 0
[13,] 0 0 0 0 0 0 0 0
[14,] 0 0 0 0 0 0 0 0
[15,] 0 0 0 0 0 0 0 0
[16,] 0 0 0 0 0 0 0 0
[17,] 0 0 0 0 0 0 0 0
[,18]
[1,] 0
[2,] 0
[3,] 0
[4,] 0
[5,] 0
[6,] 0
[7,] 0
[8,] 0
[9,] 0
[10,] 0
[11,] 0
[12,] 0
[13,] 0
[14,] 0
[15,] 0
[16,] 0
[17,] 0
How can I find the number of values which has 1 in neighbour? (neighbour of a pixel is the value above the value, below the value, to the right, to the left, top right, top left, below left, below right).
I just need to get a way of devising how I can even find the number of values which has 1 above/below it. If I get that, I'll be able to solve the other variables of the problem (top right and such).
I've been experimenting around with which such as which(imageMatrix == 1, arr.ind = TRUE)[1,1]. But I cannot figure it out. (ImageMatrix is the name of the matrix)
Can anyone lend me a hand on how I can begin with the problem so I get a jump?
In the following we use the example matrix m generated reproducibly in the Note at the end.
1) Append a row and column of zeros on each end and then apply rollsum , transpose, apply it again and transpose again. Finally subtract the original matrix so that only neighbors are counted. This solution is the most compact of those here.
library(zoo)
m2 <- rbind(0, cbind(0, m, 0), 0)
t(rollsum(t(rollsum(m2, 3)), 3)) - m
## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 3 5 3 2
## [2,] 3 5 6 4 2
## [3,] 2 6 5 5 2
## [4,] 2 5 2 2 1
## [5,] 1 3 2 2 1
2) A second approach is the following. It would be much faster than the others here.
nr <- nrow(m)
nc <- ncol(m)
mm <- cbind(m[, -1], 0) + m + cbind(0, m[, -nc])
rbind(mm[-1, ], 0) + mm + rbind(0, mm[-nr, ]) - m
## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 3 5 3 2
## [2,] 3 5 6 4 2
## [3,] 2 6 5 5 2
## [4,] 2 5 2 2 1
## [5,] 1 3 2 2 1
3) Using loops we can write the following. It is probably the most straight forward. Note that subscripting by 0 omits that element and i %% 6 equals i if i is in 1, 2, 3, 4, 5 and equals 0 if i equals 0 or 6.
nr <- nrow(m); nr1 <- nr + 1
nc <- ncol(m); nc1 <- nc + 1
mm <- 0 * m # initialize result
for(i in seq_len(nr))
for(j in seq_len(nc))
mm[i, j] <- sum(m[seq(i-1, i+1) %% nr1, seq(j-1, j+1) %% nc1]) - m[i,j]
mm
## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 3 5 3 2
## [2,] 3 5 6 4 2
## [3,] 2 6 5 5 2
## [4,] 2 5 2 2 1
## [5,] 1 3 2 2 1
Note
set.seed(123)
m <- +matrix(rnorm(25) > 0, 5)
m
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0 1 1 1 0
## [2,] 0 1 1 1 0
## [3,] 1 0 1 0 0
## [4,] 1 0 1 1 0
## [5,] 1 0 0 0 0

Set values withing a range equal to 1 and rest to 0

I have a 7000 X 7000 matrix in R. For example purpose I will use a smaller matrix as following:-
a <- matrix(c(0:-9, 1:-8, 2:-7, 3:-6, 4:-5, 5:-4, 6:-3, 7:-2, 8:-1, 9:0),
byrow = TRUE, ncol = 10, nrow = 10)
I want to create a new matrix which has values equal to 1 where the absolute values in matrix a are between the closed interval of 2 and 5. And rest all other values equal to zero.
This would make the following matrix:-
b <- matrix(c(0,0,1,1,1,1,0,0,0,0
0,0,0,1,1,1,1,0,0,0
1,0,0,0,1,1,1,1,0,0
1,1,0,0,0,1,1,1,1,0
1,1,1,0,0,0,1,1,1,1
1,1,1,1,0,0,0,1,1,1
0,1,1,1,1,0,0,0,1,1
0,0,1,1,1,1,0,0,0,1
0,0,0,1,1,1,1,0,0,0
0,0,0,0,1,1,1,1,0,0),
byrow = TRUE, ncol = 10, nrow = 10)
I can do this using for loop, but I just want to know if there is a much better and effcient solution to do this.
Thanks in advance.
You can just write down the comparison. It gives you a logical matrix and you can then use unary + to turn the result into an integer matrix.
+(abs(a) >= 2 & abs(a) <= 5)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 0 0 1 1 1 1 0 0 0 0
# [2,] 0 0 0 1 1 1 1 0 0 0
# [3,] 1 0 0 0 1 1 1 1 0 0
# [4,] 1 1 0 0 0 1 1 1 1 0
# [5,] 1 1 1 0 0 0 1 1 1 1
# [6,] 1 1 1 1 0 0 0 1 1 1
# [7,] 0 1 1 1 1 0 0 0 1 1
# [8,] 0 0 1 1 1 1 0 0 0 1
# [9,] 0 0 0 1 1 1 1 0 0 0
#[10,] 0 0 0 0 1 1 1 1 0 0
Perhaps you can try
> +((abs(a) - 2) * (abs(a) - 5) <= 0)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 1 1 1 1 0 0 0 0
[2,] 0 0 0 1 1 1 1 0 0 0
[3,] 1 0 0 0 1 1 1 1 0 0
[4,] 1 1 0 0 0 1 1 1 1 0
[5,] 1 1 1 0 0 0 1 1 1 1
[6,] 1 1 1 1 0 0 0 1 1 1
[7,] 0 1 1 1 1 0 0 0 1 1
[8,] 0 0 1 1 1 1 0 0 0 1
[9,] 0 0 0 1 1 1 1 0 0 0
[10,] 0 0 0 0 1 1 1 1 0 0

Random matrix with diagonal entries 0's and all other entries are 0's and 1's [duplicate]

This question already has an answer here:
Set diagonal of a matrix to zero in R
(1 answer)
Closed 2 years ago.
I tried using the rbern function in R but I realized that the diagonal entries are not all 0's.
This would be a possible way:
m <- 10
n <- 10
mat <- matrix(sample(0:1,m*n, replace=TRUE),m,n)
diag(mat) <- 0
#> mat
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 0 1 1 0 1 0 0 0 1 0
# [2,] 1 0 1 1 0 0 1 0 0 1
# [3,] 0 0 0 1 0 1 0 0 1 0
# [4,] 0 1 0 0 0 0 0 0 1 0
# [5,] 0 1 1 1 0 0 1 1 0 0
# [6,] 1 0 1 0 1 0 0 0 1 0
# [7,] 1 1 1 0 0 0 0 0 1 1
# [8,] 1 0 1 1 1 1 1 0 1 1
# [9,] 1 1 1 1 1 1 0 0 0 1
#[10,] 1 0 1 0 1 0 0 0 1 0

How to form the matrix of logical '1' and '0' using two vectors and logical operators in r?

Here is Matlab code to form the matrix of logical values of '0' and '1'
A=[1 2 3 4 5 6 7 8 9 10 ];
N = numel(A);
step = 2; % Set this to however many zeros you want to add each column
index = N:-step:1;
val = (1:N+step).' <= index;
Which result in
val=
1 1 1 1 1
1 1 1 1 1
1 1 1 1 0
1 1 1 1 0
1 1 1 0 0
1 1 1 0 0
1 1 0 0 0
1 1 0 0 0
1 0 0 0 0
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
How to do same task in r ,particularly val = (1:N+step).' <= indexthis step?
One option is
i <- seq_len(ncol(m1))
sapply(rev(i), function(.i) {
m1[,.i][sequence(.i *2)] <- 1
m1[,.i]
})
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 1 1 1 1
# [2,] 1 1 1 1 1
# [3,] 1 1 1 1 0
# [4,] 1 1 1 1 0
# [5,] 1 1 1 0 0
# [6,] 1 1 1 0 0
# [7,] 1 1 0 0 0
# [8,] 1 1 0 0 0
# [9,] 1 0 0 0 0
#[10,] 1 0 0 0 0
#[11,] 0 0 0 0 0
#[12,] 0 0 0 0 0
Or vectorize it
i1 <- rep(i, rev(2*i))
m1[cbind(ave(i1, i1, FUN = seq_along), i1)] <- 1
m1
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 1 1 1 1
# [2,] 1 1 1 1 1
# [3,] 1 1 1 1 0
# [4,] 1 1 1 1 0
# [5,] 1 1 1 0 0
# [6,] 1 1 1 0 0
# [7,] 1 1 0 0 0
# [8,] 1 1 0 0 0
# [9,] 1 0 0 0 0
#[10,] 1 0 0 0 0
#[11,] 0 0 0 0 0
#[12,] 0 0 0 0 0
Or another option without creating a matrix beforehand
n <- 5
i1 <- seq(10, 2, by = -2)
r1 <- c(rbind(i1, rev(i1)))
matrix(rep(rep(c(1, 0), n), r1), ncol = n)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 1 1 1 1
# [2,] 1 1 1 1 1
# [3,] 1 1 1 1 0
# [4,] 1 1 1 1 0
# [5,] 1 1 1 0 0
# [6,] 1 1 1 0 0
# [7,] 1 1 0 0 0
# [8,] 1 1 0 0 0
# [9,] 1 0 0 0 0
#[10,] 1 0 0 0 0
#[11,] 0 0 0 0 0
#[12,] 0 0 0 0 0
data
m1 <- matrix(0, 12, 5)

Count the number of appeareances in a list, trick?

I have a matrix of 1 and 0. The rules concerning this table is as follows.
I would like to count the number of times a serie of 1,1 appears (where the 1 are not separated by 0!) and make the same thing for a serie of 1,1,1. I have tried colSums but it's seemed not to be very appropriate.
the matrix final is
t1 t2 t3 t4 t5 t6 t7
[1,] 0 0 0 0 1 1 0
[2,] 0 0 1 1 0 0 1
[3,] 1 1 0 0 0 0 0
[4,] 0 0 1 1 1 0 0
[5,] 0 0 1 1 0 0 0
[6,] 1 1 0 0 0 0 0
[7,] 0 0 0 0 0 0 1
[8,] 0 0 0 0 1 1 0
[9,] 1 1 0 0 1 1 0
[10,] 0 0 0 0 0 1 1
[11,] 1 1 0 0 0 0 0
[12,] 0 0 1 1 0 0 0
[13,] 0 0 0 0 0 0 0
[14,] 0 0 0 0 0 0 1
[15,] 0 0 0 0 0 0 0
Therefore for the first row I would like to have 1 time a serie of 1,1 and 0 time a serie of 1,1,1. For row 4 I would like to have 0 time a serie of 1,1 but 1 time a serie of 1,1,1.
Can anyone tell me whats wrong with the following code for a serie of 1,1?
occ <- matrix()
occ_temp <- matrix
for (j in 1:nrow(final)){
for (i in 2:7){
if (sum(final[j,i-1:i])==2){occ_temp[j,i-1]=1}
}
occ[j] <- sum(occ_temp)
}
We can loop through the rows with apply, get the run-length-type with rle, extract the lengths where the values are 1, check that are equal to 'n1' and 'n2', and get the sum.
n1 <- 2
n2 <- 3
res <- t(apply(m1, 1, FUN=function(x) {
x1 <- with(rle(x), lengths[!!values])
c(sum(x1==n1), sum(x1==n2))
}))
colnames(res) <- paste0("count", c(11, 111))
res
# count11 count111
# [1,] 1 0
# [2,] 1 0
# [3,] 1 0
# [4,] 0 1
# [5,] 1 0
# [6,] 1 0
# [7,] 0 0
# [8,] 1 0
# [9,] 2 0
#[10,] 1 0
#[11,] 1 0
#[12,] 1 0
#[13,] 0 0
#[14,] 0 0
#[15,] 0 0

Resources