fill matrix with numbers in each row to create a parttern - r

I'm trying to generate a trip parttern using a matrix.
Glastonbury Munich Venice Paris Ibiza Kamar-Taj
[1,] 1 2 3 4 5 6
[2,] 1 2 3 4 5 0
[3,] 1 2 3 4 0 0
[4,] 1 2 3 0 0 0
[5,] 1 2 0 0 0 0
[6,] 3 2 1 4 5 6
[7,] 0 2 3 4 1 0
[8,] 0 1 2 0 0 0
[9,] 5 1 3 2 0 0
each row represents a single trip, and the number in a cell represents the order they visited each locations. Zero means they didn't visit that place.
currently I'm creating it like this:
tripMatrix <- list()
tripMatrix[[ 1 ]] <- c(1, 2, 3, 4, 5, 6)
tripMatrix[[ 2 ]] <- c(1, 2, 3, 4, 5, 0)
tripMatrix[[ 3 ]] <- c(1, 2, 3, 4, 0, 0)
tripMatrix[[ 4 ]] <- c(1, 2, 3, 0, 0, 0)
tripMatrix[[ 5 ]] <- c(1, 2, 0, 0, 0, 0)
tripMatrix[[ 6 ]] <- c(3, 2, 1, 4, 5, 6)
tripMatrix[[ 7 ]] <- c(0, 2, 3, 4, 1, 0)
tripMatrix[[ 8 ]] <- c(4, 5, 3, 2, 1, 0)
tripMatrix[[ 8 ]] <- c(0, 1, 2, 0, 0, 0)
tripMatrix[[ 10 ]] <- c(5, 1, 3, 2, 0, 0)
trips <- matrix(unlist(tripMatrix), ncol = 6, byrow = TRUE)
I can only do this for a few rows, but I'll like to generate N number of rows with different conbinations of places visited during a trip.
Please I can I do this for N number of rows without having to manually create a list of trips?

Starting with a math approach by thinking about the theoretical number of trips. For example, out of the 6 places, you can choose 4 to visit (i.e. 6C4 = 6 choose 4) and among these 4 places, you can visit them in any order giving 4! (4 factorial) ways of visiting them in different sequence. The same applies to other number of places, giving a theoretical number of 6! + 6C5*5! + 6C4*4! + 6C3*3! + 6C2*2! + 6C1 = 1956 possible trips.
Here is an option using utils::combn and RcppAlgos::permuteGeneral to generate all 1,956 possibilities:
nc <- 6L
l <- lapply(1L:nc, function(n) combn(1L:nc, n,
function(x) {
if (length(x) > 1L) {
p <- RcppAlgos::permuteGeneral(x, length(x))
a <- matrix(0L, nrow=nrow(p), ncol=nc)
a[cbind(c(row(p)), c(p))] <- col(p)
} else {
a <- integer(nc)
a[x] <- 1L
}
a
}, simplify=FALSE))
m <- do.call(rbind, unlist(l, recursive=FALSE))
head(m, 20):
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 0 0 0 0
[2,] 0 1 0 0 0 0
[3,] 0 0 1 0 0 0
[4,] 0 0 0 1 0 0
[5,] 0 0 0 0 1 0
[6,] 0 0 0 0 0 1
[7,] 1 2 0 0 0 0
[8,] 2 1 0 0 0 0
[9,] 1 0 2 0 0 0
[10,] 2 0 1 0 0 0
[11,] 1 0 0 2 0 0
[12,] 2 0 0 1 0 0
[13,] 1 0 0 0 2 0
[14,] 2 0 0 0 1 0
[15,] 1 0 0 0 0 2
[16,] 2 0 0 0 0 1
[17,] 0 1 2 0 0 0
[18,] 0 2 1 0 0 0
[19,] 0 1 0 2 0 0
[20,] 0 2 0 1 0 0

You could use sample and replicate like :
N <- 10
unique_trip_locations <- 6
t(replicate(N, sample(0:unique_trip_locations, unique_trip_locations)))
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 2 3 1 5 0 6
# [2,] 5 3 6 2 0 1
# [3,] 2 4 1 3 0 5
# [4,] 1 6 5 3 0 2
# [5,] 6 3 1 4 2 0
# [6,] 1 2 0 6 5 4
# [7,] 5 1 3 0 4 6
# [8,] 0 4 6 2 3 1
# [9,] 0 5 1 3 2 6
#[10,] 5 6 0 1 3 2
However, this has got one limitation that 0 can occur max only once like all other numbers.

You can use brute force to do it, and in this case it is totally feasible.
I think mine is clearer than the previous answers:
vector<-c(1:6, rep(0,6)) # This is what you need as combinations
Data<-data.frame() # Initilizing Dataframe
i<-1 # Just to check total iterations
N<-1956 # Number of unique combinations to get
while(nrow(Data)<=N){
i<- i+1
Data<- rbind(Data,sample(vector, 6, replace = F))
Data<-Data[!duplicated(Data),]
}

Here is a base R solution without using any additional packages:
# define your own permutation function
perm <- function(x) {
if (length(x)==1) return(t(x))
subset(r <- do.call(expand.grid,replicate(length(x),x,simplify = F)), colSums(apply(r, 1, duplicated))==0)
}
# define function that give all permutations with given number of posistions
f <- function(x,vl) {
p <- perm(x)
unname(t(apply(p, 1, function(q) replace(rep(0,vl),q,seq_along(q)))))
}
# generate the desired output
v = 1:6
res <- do.call(rbind,
Map(f,
vl = length(v),
unlist(sapply(seq_along(v), function(k) combn(v,k,simplify = F)),recursive = F)))
such that
> head(res,25)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 0 0 0 0
[2,] 0 1 0 0 0 0
[3,] 0 0 1 0 0 0
[4,] 0 0 0 1 0 0
[5,] 0 0 0 0 1 0
[6,] 0 0 0 0 0 1
[7,] 2 1 0 0 0 0
[8,] 1 2 0 0 0 0
[9,] 2 0 1 0 0 0
[10,] 1 0 2 0 0 0
[11,] 2 0 0 1 0 0
[12,] 1 0 0 2 0 0
[13,] 2 0 0 0 1 0
[14,] 1 0 0 0 2 0
[15,] 2 0 0 0 0 1
[16,] 1 0 0 0 0 2
[17,] 0 2 1 0 0 0
[18,] 0 1 2 0 0 0
[19,] 0 2 0 1 0 0
[20,] 0 1 0 2 0 0
[21,] 0 2 0 0 1 0
[22,] 0 1 0 0 2 0
[23,] 0 2 0 0 0 1
[24,] 0 1 0 0 0 2
[25,] 0 0 2 1 0 0

Related

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)

find All Combinations of 0's and 1's with specific number of 1's

I want to find a matrix with all possible combinations of 0's and 1's. The conditions of these possible combinations are no reputation of individual possibilities, and for each possible vector has the specified number of 1's. For example, I have a number of object n = 6, and a number of samples r = 3, which means 6 slots, in each slot, (possible combination), there is a number of 1's = 3. Using the choose() function in R, we can find the number of possibilities which is 20.
choose(n=6,k=3) #calculate the number of combinations without replacement/repetition
The desirable output matrix of all possible combination as below:
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, 0 1 1 1 0 0
9, 0 1 1 0 1 0
10,0 1 1 0 0 1
11,0 0 1 1 1 0
12,0 0 1 1 0 1
14,0 0 0 1 1 1
15,1 0 0 1 1 0
16,0 1 0 1 1 0
17,1 0 0 1 0 1
18,1 0 0 0 1 1
These possiblities should be equal to 20, howover, I found 18 only.
I will apply this concept for a large amount of data set, such as instead of 6 slots, and 3 1's it will be 200 slots and 100 1's, respectively. Therefore, I need an algorithm or a built-in function in R to give me the output.
Thanks.
t(combn(6,3,function(x)replace(numeric(6),x,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
You can write a function:
fun=function(n,m)t(combn(n,m,function(x)replace(numeric(n),x,1)))
fun(6,3
This is simply permutations of the multiset 0:1. There are a couple of libraries capable for handling these efficiently: RcppAlgos (I am the author) and arrangements.
RcppAlgos::permuteGeneral(1:0, freqs = c(3, 3))
arrangements::permutations(x = 1:0, freq = c(3, 3))
Both give the desired result. You will note that the vector passed is in descending order (i.e. 1:0). This is so, because both of the libraries produce their output in lexicographical order.
As noted in the comments, for your real data none of the posted solutions will work as the number of results is way too big.
RcppAlgos::permuteCount(0:1, freqs = c(100,100))
[1] 9.054851e+58
arrangements::npermutations(x = 0:1, freq = c(100, 100), bigz = TRUE)
Big Integer ('bigz') :
[1] 90548514656103281165404177077484163874504589675413336841320
Since generating this amount of data at one time is simply not feasible, both of the packages, arrangements and RcppAlgos, offer alternative approaches that will allow one to tackle larger problems.
arrangements
For the package arrangements, you can set up an iterator that allows the user to generate combinations/permutations n at a time avoiding the overhead of generating all of them.
library(arrangements)
iperm <- ipermutations(x = 1:0, freq = c(3,3))
## get the first 5 permutations
iperm$getnext(d = 5)
[,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
## get the next 5 permutations
iperm$getnext(d = 5)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 1 0 1 0
[2,] 1 0 1 0 0 1
[3,] 1 0 0 1 1 0
[4,] 1 0 0 1 0 1
[5,] 1 0 0 0 1 1
RcppAlgos
For RcppAlgos, there are arguments lower and upper that allow for generations of specific chunks.
library(RcppAlgos)
permuteGeneral(1:0, freqs = c(3,3), lower = 1, upper = 5)
[,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
permuteGeneral(1:0, freqs = c(3,3), lower = 6, upper = 10)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 1 0 1 0
[2,] 1 0 1 0 0 1
[3,] 1 0 0 1 1 0
[4,] 1 0 0 1 0 1
[5,] 1 0 0 0 1 1
As these chunks are generated independently, one can easily generate and analyze in parallel:
library(parallel)
mclapply(seq(1,20,5), function(x) {
a <- permuteGeneral(1:0, freqs = c(3,3), lower = x, upper = x + 4)
## Do some analysis
}, mc.cores = detectCores() - 1)
You will not notice any speedup for this small example, but there is a noticeable gain as the number of results get large.
There is a lot more information on this topic in a summary I wrote to the question: R: Permutations and combinations with/without replacement and for distinct/non-distinct items/multiset.

Obtain matrices by switch a one and a zero-Local search

Let's start with the following matrix.
M <- matrix(c(0,0,0,1,0,0,1,1,
0,0,1,0,0,1,1,0,
0,0,0,0,0,1,1,1,
0,0,0,1,1,0,1,0,
0,0,0,1,1,1,0,0,
0,0,1,0,1,0,0,1),nrow = 8,ncol = 6)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 0 0 0 0 0
[2,] 0 0 0 0 0 0
[3,] 0 1 0 0 0 1
[4,] 1 0 0 1 1 0
[5,] 0 0 0 1 1 1
[6,] 0 1 1 0 1 0
[7,] 1 1 1 1 0 0
[8,] 1 0 1 0 0 1
I want to obtain set of matrices by switching ones and zeros. For each column, starting from column 1, I wanna obtain set of matrices by switching 1 in (4,1) with 0 in (1,1), (2,1), (3,1), (5,1), (6,1) and then do the same for 1s in (7,1) and (8,1). Then continue to the other columns. There are altogether
90 matrices (15 for each column, 15*6) after switching. This is just an example. I have bigger size matrices. How do I generalize for other cases?
Here's a solution. You could wrap the whole thing up into a function. It produces a list of lists of matrices, results, where results[[i]] is a list of matrices with the ith column switched.
column_switcher = function(x) {
ones = which(x == 1)
zeros = which(x == 0)
results = matrix(rep(x, length(ones) * length(zeros)), nrow = length(x))
counter = 1
for (one in ones) {
for (zero in zeros) {
results[one, counter] = 0
results[zero, counter] = 1
counter = counter + 1
}
}
return(results)
}
switched = lapply(1:ncol(M), function(col) column_switcher(M[, col]))
results = lapply(seq_along(switched), function(m_col) {
lapply(1:ncol(switched[[m_col]]), function(i) {
M[, m_col] = switched[[m_col]][, i]
return(M)
})
})
results[[1]]
# [[1]]
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 1 0 0 0 0 0
# [2,] 0 0 0 0 0 0
# [3,] 0 1 0 0 0 1
# [4,] 0 0 0 1 1 0
# [5,] 0 0 0 1 1 1
# [6,] 0 1 1 0 1 0
# [7,] 1 1 1 1 0 0
# [8,] 1 0 1 0 0 1
#
# [[2]]
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 0 0 0 0 0 0
# [2,] 1 0 0 0 0 0
# [3,] 0 1 0 0 0 1
# [4,] 0 0 0 1 1 0
# [5,] 0 0 0 1 1 1
# [6,] 0 1 1 0 1 0
# [7,] 1 1 1 1 0 0
# [8,] 1 0 1 0 0 1
#
# ...
Checking the length of the list and the lengths of the sublists, they're all there.
length(results)
# [1] 6
lengths(results)
# [1] 15 15 15 15 15 15

Is there a way to generate a matrix in R of 0's and 1's to satisfy specific row and column totals?

I want to generate a 7 column by 10 row matrix with a total of exactly 20 randomly generated 1's, but with at least two 1's per row and two 1's per column. How could I do that?
Also, how would the code be different if I wanted to set a range of acceptable row and column totals instead of minimums?
Thanks!
I feel like there should be a more elegant solution, but here's a ball of duct tape:
matbuilder <- function(n,nrow,ncol) {
finished <- F
while(!finished) {
trial <- matrix(sample(c(rep(1,n),rep(0,nrow*ncol-n))),nrow=nrow,ncol=ncol)
if(all(rowSums(trial)>=2 & all(colSums(trial)>=2))) finished <- T
}
return(trial)
}
x <- matbuilder(20, 10, 7)
x
## [,1] [,2] [,3] [,4] [,5] [,6] [,7]
## [1,] 1 1 0 0 0 0 0
## [2,] 0 0 0 0 1 0 1
## [3,] 0 1 0 0 0 1 0
## [4,] 1 0 0 0 1 0 0
## [5,] 0 1 0 0 0 1 0
## [6,] 0 0 1 1 0 0 0
## [7,] 0 0 1 1 0 0 0
## [8,] 0 0 0 0 1 0 1
## [9,] 0 0 0 0 0 1 1
## [10,] 0 1 1 0 0 0 0
sum(x)
## [1] 20
rowSums(x)
## [1] 2 2 2 2 2 2 2 2 2 2
colSums(x)
## [1] 2 4 3 2 3 3 3
Or, to give a range of acceptable row/column totals...
matbuilder <- function(n,nrow,ncol,rowmin,rowmax,colmin,colmax,ntimeout=100000) {
finished <- F
i <- 1
trial <- NA
while(!finished) {
trial <- matrix(sample(c(rep(1,n),rep(0,nrow*ncol-n))),nrow=nrow,ncol=ncol)
if(all(rowSums(trial)>=rowmin) & all(rowSums(trial)<=rowmax) & all(colSums(trial)>=colmin) & all(colSums(trial)<=colmax)) finished <- T
i <- i+1
if(i>ntimeout) {
finished <- T
cat("sorry boss, timeout.")
}
}
return(trial)
}
x <- matbuilder(25,10,7,rowmin=2,rowmax=3,colmin=2,colmax=4)
x
## [,1] [,2] [,3] [,4] [,5] [,6] [,7]
## [1,] 1 0 0 0 0 1 1
## [2,] 0 1 1 0 0 0 1
## [3,] 1 0 0 0 1 0 0
## [4,] 1 0 1 1 0 0 0
## [5,] 1 0 0 0 0 1 1
## [6,] 0 1 1 1 0 0 0
## [7,] 0 0 0 1 0 0 1
## [8,] 0 0 1 0 1 0 0
## [9,] 0 0 0 1 1 0 0
## [10,] 0 0 0 0 1 1 0
sum(x)
## [1] 25
rowSums(x)
## [1] 3 3 2 3 3 3 2 2 2 2
colSums(x)
## [1] 4 2 4 4 4 3 4
This one involves sampling a matrix of indices such that each row is repeated twice and columns are repeated at least 2 times.
set.seed(42)
m = matrix(rep(0, 70), nrow = 10)
#Sample rows 1-10 twice
rows = sample(c(1:10, 1:10))
#Sample columns 1-7 twice and additional 6 to make 20
columns = sample(c(sample(1:7, 6, replace = TRUE), 1:7, 1:7))
#Create a matrix of indices that should be 1
inds = cbind(rows, columns)
#Remove duplicates in inds if any (Refer: https://stackoverflow.com/q/44555420/7128934)
inds[,2] = replace(x = inds[,2],
list = duplicated(inds),
values = sample(x = columns[!(columns %in% inds[,2][duplicated(inds)])],
size = 1))
m[inds] = 1
#Check
rowSums(m)
#[1] 2 2 2 2 2 2 2 2 2 2
colSums(m)
#[1] 4 2 2 3 2 2 5
sum(m)
#[1] 20

R which function displays wrong row numbers

I am trying to save the row number for values equal to one, for every column seperatly in a matrix (matx). The matrix should contain 0's for every other object. It somehow worked to give me numbers which are just a little bit smaller (1 value smaller in the beginning, two and three later on), but not the right values. The original matrix has just values of 0 and 1.
My try:
matx<-replicate(n=100,rbinom(n= 250, size=1, prob = 0.01))
maty<-apply(!matx, 2, function(x) ifelse(x==0,
which(x %in% 1),
x==0))
also tried:
maty<-apply(!matx, 2, function(x) ifelse(x>0, as.integer(rownames(matx)), 0))
The second attempt just leaves me with NA's and 0's instead of the row number.
Assuming that #akrun's interpretation is correct (it's also how I read the question) you can also use the row function:
matx * row(matx)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0 1 0 0 0
# [2,] 0 0 2 0 0
# [3,] 3 3 3 0 0
# [4,] 4 4 0 0 0
# [5,] 5 0 0 5 0
# [6,] 6 6 6 0 0
# [7,] 0 0 0 7 0
# [8,] 8 0 8 8 0
# [9,] 9 9 9 9 0
# [10,] 0 0 0 10 0
If we need to replace the '1s' (in the binary matrix) with the corresponding row numbers leaving the '0s' as such, we can can which with arr.ind=TRUE to get the row/column index of non-zero numbers, use that index to replace the 1s with the row index column from 'ind'. Here, I created a copy of 'matx' (ie. 'maty') in case the original matrix is needed.
maty <- matx
ind <- which(matx!=0, arr.ind=TRUE)
maty[ind] <- ind[,1]
maty
# [,1] [,2] [,3] [,4] [,5]
#[1,] 0 1 0 0 0
#[2,] 0 0 2 0 0
#[3,] 3 3 3 0 0
#[4,] 4 4 0 0 0
#[5,] 5 0 0 5 0
#[6,] 6 6 6 0 0
#[7,] 0 0 0 7 0
#[8,] 8 0 8 8 0
#[9,] 9 9 9 9 0
#[10,] 0 0 0 10 0
and original matrix
matx
# [,1] [,2] [,3] [,4] [,5]
#[1,] 0 1 0 0 0
#[2,] 0 0 1 0 0
#[3,] 1 1 1 0 0
#[4,] 1 1 0 0 0
#[5,] 1 0 0 1 0
#[6,] 1 1 1 0 0
#[7,] 0 0 0 1 0
#[8,] 1 0 1 1 0
#[9,] 1 1 1 1 0
#[10,] 0 0 0 1 0
NOTE: This could be also used for non-numeric elements
Or a base R modification of apply solution in #eipi's post would be
apply(matx, 2,function(x) ifelse(x!=0, seq_along(x), 0) )
data
set.seed(24)
matx <- matrix(sample(0:1, 10*5, replace=TRUE), nrow=10)
If your original matx is purely 0s and 1s then this show work:
maty <- matx * row(matx)
an example:
> matx # stealing from akrun
[,1] [,2] [,3] [,4] [,5]
[1,] 0 1 0 0 0
[2,] 0 0 1 0 0
[3,] 1 1 1 0 0
[4,] 1 1 0 0 0
[5,] 1 0 0 1 0
[6,] 1 1 1 0 0
[7,] 0 0 0 1 0
[8,] 1 0 1 1 0
[9,] 1 1 1 1 0
[10,] 0 0 0 1 0
> matx * row(matx)
[,1] [,2] [,3] [,4] [,5]
[1,] 0 1 0 0 0
[2,] 0 0 2 0 0
[3,] 3 3 3 0 0
[4,] 4 4 0 0 0
[5,] 5 0 0 5 0
[6,] 6 6 6 0 0
[7,] 0 0 0 7 0
[8,] 8 0 8 8 0
[9,] 9 9 9 9 0
[10,] 0 0 0 10 0
Here's a way to do it using apply:
library(zoo) # For index function
apply(matx, 2, function(x) ifelse(x==1, index(x), 0))

Resources