I am relatively new to R and trying to create a nested for loop that will increment over a sequence of random numbers and add it to some variables in the table if a specific condition is met. Below is the sample code:
#create sample table
tab <- matrix(c(7, 5, 0, 19, 3, 1, 17, 8, 0, 7, 6, 0, 3, 1, 1), ncol=3, byrow=TRUE)
colnames(tab) <- c('V1','V2','V3')
rownames(tab) <- c('abc','def','ghi','jkl', 'mne')
tab <- as.data.frame(tab)
tab
#get random variables
n = 3
rand_num <- round(rnorm(n, mean = 3, sd = 1), digits = 0)
rand_num
#create for loop do add random variables to values where v3 = 0
tab2 <- tab
for(i in 1:nrow(tab))
{
if(tab2$V3[i] == 0)
{
for(p in seq(from = 1, to = 3)
tab2$V2[i] <- tab2$V2[i] rand_num[p]
}
}
tab
V1 V2 V3
abc 7 5 0
def 19 3 1
ghi 17 8 0
jkl 7 6 0
mne 3 1 1
tab2
V1 V2 V3
abc 7 5 0
def 19 3 1
ghi 17 8 0
jkl 7 6 0
mne 3 1 1
However, the for loop doesn't work as expected. The expected result is below
tab2
V1 V2 V3
abc 7 7 0
def 19 3 1
ghi 17 13 0
jkl 7 8 0
mne 3 1 1
Appreciate if anyone can point me in the right direction
CodePudding user response:
Here is a vectorized solution without for
loops. I have changed the definition of n
.
tab <- matrix(c(7, 5, 0, 19, 3, 1, 17, 8, 0, 7, 6, 0, 3, 1, 1), ncol=3, byrow=TRUE)
colnames(tab) <- c('V1','V2','V3')
rownames(tab) <- c('abc','def','ghi','jkl', 'mne')
tab <- as.data.frame(tab)
tab
#> V1 V2 V3
#> abc 7 5 0
#> def 19 3 1
#> ghi 17 8 0
#> jkl 7 6 0
#> mne 3 1 1
#get random variables
set.seed(2022)
n = sum(tab$V3 == 0)
rand_num <- round(rnorm(n, mean = 3, sd = 1), digits = 0)
rand_num
#> [1] 4 2 2
tab2 <- tab
i <- which(tab2$V3 == 0)
tab2$V2[i] <- tab2$V2[i] rand_num
Created on 2022-03-30 by the reprex package (v2.0.1)
CodePudding user response:
This line loop:
for(p in seq(from = 1, to = 3)
tab2$V2[i] <- tab2$V2[i] rand_num[p]
is adding the all three random numbers to each value of tab2$V2[i]
You can avoid loops all together here:
#Define a seed value to make the debugging repeatable
set.seed(1)
#generate random variables
rand_num <- round(rnorm(nrow(tab2), mean = 3, sd = 1), digits = 0)
tab2$V2 <- ifelse(tab2$V3 == 0, tab2$V2 rand_num, tab2$V3)