jacky_learns_to_code - 1 year ago 76
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
}
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download