E_Schyler
E_Schyler

Reputation: 117

For loop is not working, wrong output

I have a matrix called M, where each row only has two possible letters:

M <- structure(list(id1 = c("AA", "AB", "AA", "AC"), id2 = c("AA", 
"AB", "AA", "CC"), id3 = c("AA", "AA", "AB", "AC"), id4 = c("AA", 
"AB", "AB", "AA"), id5 = c("AA", "BB", "AA", "CC"), id6 = c("AA", 
"AB", "BB", "CC"), id7 = c("AA", "AB", "BB", "CC"), id8 = c("AA", 
"AB", "BB", "AC"), id9 = c("AA", "AB", "AB", "AA")), .Names = c("id1", 
"id2", "id3", "id4", "id5", "id6", "id7", "id8", "id9"), class = "data.frame", row.names = c(NA, 
-4L))
M
  # id1 id2 id3 id4 id5 id6 id7 id8 id9
# 1  AA  AA  AA  AA  AA  AA  AA  AA  AA
# 2  AB  AB  AA  AB  BB  AB  AB  AB  AB
# 3  AA  AA  AB  AB  AA  BB  BB  BB  AB
# 4  AC  CC  AC  AA  CC  CC  CC  AC  AA

I need to replace the letters so that, for each row, the first one is assigned 0 and the second 1.
So for row 2, A=0, B=1, for row 5 A=0, C=1.

I've been told to do it with the below for loop, but it doesn't seem to work, I only get results for one row back. Can anyone tell me what I'm doing wrong?

This is my code:

for (i in 1:500)
{
   results= M[i,]
   hold=unique(unlist(strsplit(unique(results),"")))
   hold=hold[is.na(hold)==F]
   sort(hold)
   results=gsub(hold[1],"0",results)
   results=gsub(hold[2],"1",results)
}

Upvotes: 0

Views: 105

Answers (1)

Cath
Cath

Reputation: 24074

You can either define results prior to your loop and modify your loop to make it write in the right row of results at each turn:

results <- as.matrix(M)
for (i in 1:nrow(M)) {
   hold <- unique(unlist(strsplit(unique(results[i, ]), "")))
   hold <- hold[!is.na(hold)]
   hold <- sort(hold)
   results[i, ] <- gsub(hold[1], "0", results[i, ])
   results[i, ] <- gsub(hold[2], "1", results[i, ])
}

Or use a slightly different approach with apply and only sub/ gsub (I added the condition on length(u_lett) because the first row of example data only has 1 letter):

results <- t(apply(M, 1, 
                  function(x) {
                     u_lett <- sort(unique(c(sub("([A-Z])[A-Z]", "\\1", x), sub("[A-Z]([A-Z])", "\\1", x))))
                     x <- gsub(u_lett[1], "0", x)
                     if (length(u_lett)>1) x <- gsub(u_lett[2], "1", x)
                     x
                  }))
results
#     id1  id2  id3  id4  id5  id6  id7  id8  id9 
#[1,] "00" "00" "00" "00" "00" "00" "00" "00" "00"
#[2,] "01" "01" "00" "01" "11" "01" "01" "01" "01"
#[3,] "00" "00" "01" "01" "00" "11" "11" "11" "01"
#[4,] "01" "11" "01" "00" "11" "11" "11" "01" "00"

Or you can mix both to get a loop/sub-gsub or a apply/strsplit solution...

Upvotes: 3

Related Questions