jacky_learns_to_code jacky_learns_to_code - 9 months ago 28
R Question

If...else within a for loop

I am writing a function to perform bit inversion for each row of a binary matrix which depends on a predefined

n
value. The
n
value will determine the number of
1
bits for each row of the matrix.

set.seed(123)
## generate a random 5 by 10 binary matrix
init <- t(replicate(5, {i <- sample(3:6, 1); sample(c(rep(1, i), rep(0, 10 - i)))}))
n <- 3
## init_1 is a used to explain my problem (single row matrix)
init_1 <- t(replicate(1, {i <- sample(3:6, 1); sample(c(rep(1, i), rep(0, 10 - i)))}))


The
bit_inversion
function does this few things:


  1. If the selected row has number of
    1's
    lesser than
    n
    , then it randomly select a few indices (
    difference
    ) and invert them. (
    0
    to
    1
    )

  2. Else if the selected row has number of
    1's
    greater than
    n
    , then it randomly select a few indices (
    difference
    ) and invert them. (
    1
    to
    0
    )

  3. Else do nothing (when the row has number of
    1's
    equals to
    n
    .)



Below is the function I implemented:

bit_inversion<- function(pop){

for(i in 1:nrow(pop)){
difference <- abs(sum(pop[i,]) - n)
## checking condition where there are more bits being turned on than n
if(sum(pop[i,]) > n){
## determine position of 1's
bit_position_1 <- sample(which(pop[i,]==1), difference)
## bit inversion
for(j in 1:length(bit_position_1)){
pop[bit_position_1[j]] <- abs(pop[i,][bit_position_1[j]] - 1)

}
}

else if (sum(pop[i,]) < n){
## determine position of 0's
bit_position_0 <- sample(which(pop[i,]==0), difference)
## bit inversion
for(j in 1:length(bit_position_0)){
pop[bit_position_0[j]] <- abs(pop[bit_position_0[j]] - 1)

}
}
}

return(pop)
}


Outcome:

call <- bit_inversion(init)
> rowSums(call) ## suppose to be all 3
[1] 3 4 5 4 3


But when using
init_1
(a single row matrix), the function seems to work fine.

Outcome:

call_1 <- bit_inversion(init_1)
> rowSums(call)
[1] 3


Is there a mistake in my
for
and
if...else
loop?

Answer Source

Change the line in 'j' for loop

pop[bit_position_1[j]] <- abs(pop[i,][bit_position_1[j]] - 1)

into

pop[i,bit_position_1[j]] <- abs(pop[i,][bit_position_1[j]] - 1)

You forgot the row index.

And, here is a more compact version of your for loop:

for(i in 1:nrow(pop)){
  difference <- abs(sum(pop[i,]) - n)
  logi <- sum(pop[i,]) > n
  pop[i,sample(which(pop[i,]==logi), difference)] <- !logi
}