Home > Software engineering >  How to access the iteration count in a for-loop inside a conditional if-then statement in R?
How to access the iteration count in a for-loop inside a conditional if-then statement in R?

Time:09-16

This is my first time working on a for-loop and I am fairly new to R. I'm having trouble running an ifelse() function using the iteration counter of a for-loop. Below is data frame output from running the code posted at the bottom (looping only once), with a column manually added on the far right to explain the error in that row. Column concat_1 should simply be the concatenation of seqBase and grpRank when loop iteration i = 1:

> nCode
# A tibble: 8 x 6
  Name  Group nmCnt seqBase grpRnk concat_1   << ERROR in concat_1 column when loop i = 1
  <chr> <dbl> <int>   <int>  <dbl>    <dbl>
1 R         0     1       1      0      1  
2 R         0     2       2      0      1        seqBase   grpRank = 2
3 X         0     1       1      0      1  
4 X         1     2       2      1      1.1      seqBase   grpRank = 2.1 
5 X         1     3       2      2      1.2      seqBase   grpRank = 2.2 
6 X         0     4       3      0      1        seqBase   grpRank = 3
7 X         0     5       4      0      1        seqBase   grpRank = 4
8 X         0     6       5      0      1        seqBase   grpRank = 5

Why is the below ifelse() (comment # to its right) producing incorrect results?

Code:

library(dplyr)
library(stringr)

myDF1 <-
  data.frame(
    Name = c("R","R","X","X","X","X","X","X"),
    Group = c(0,0,0,1,1,0,0,0)
  )

nCode <-  myDF1 %>%
  group_by(Name) %>%
  mutate(nmCnt = row_number()) %>%
  ungroup() %>%
  mutate(seqBase = ifelse(Group == 0 | Group != lag(Group), nmCnt,0)) %>%
  mutate(seqBase = na_if(seqBase, 0)) %>%
  group_by(Name) %>%
  fill(seqBase) %>%
  mutate(seqBase = match(seqBase, unique(seqBase))) %>%
  ungroup %>%
  mutate(grpRnk = ifelse(Group > 0, sapply(1:n(), function(x) sum(Name[1:x]==Name[x] & Group[1:x] == Group[x])),0))

for(i in 1:1) {
  
  concat_col <- str_c("concat_",i)
  reSeq_col <- str_c("reSeq_",i)
  
  nCode <- nCode %>% 
    mutate(!! concat_col:= as.numeric(paste0(ifelse(i==1,seqBase,reSeq_col),".",grpRnk))) # problem lies here
}

CodePudding user response:

There you go sir

myDF1 <-
  data.frame(
    Name = c("R","R","X","X","X","X","X","X"),
    Group = c(0,0,0,1,1,0,0,0)
  )

nCode <-  myDF1 %>%
  group_by(Name) %>%
  mutate(nmCnt = row_number()) %>%
  ungroup() %>%
  mutate(seqBase = ifelse(Group == 0 | Group != lag(Group), nmCnt,0)) %>%
  mutate(seqBase = na_if(seqBase, 0)) %>%
  group_by(Name) %>%
  fill(seqBase) %>%
  mutate(seqBase = match(seqBase, unique(seqBase))) %>%
  ungroup %>%
  mutate(grpRnk = ifelse(Group > 0, sapply(1:n(), function(x) sum(Name[1:x]==Name[x] & Group[1:x] == Group[x])),0))

library(magrittr)
nCode %<>% mutate(
  contact_col=as.numeric(
    paste0(seqBase,".",grpRnk)
  )
)

# %<>% is just a regular pipe with a fancy way to asign to variable (instead of `<-`)




CodePudding user response:

Below is a working example of code that resolves the issue. More complete explanations and example are at How to iteratively add to a data frame in R using a for-loop? and Unquote the variable name on the right side of mutate function in dplyr

library(dplyr)
library(rlang)
library(stringr)

myDF1 <-
  data.frame(
    Name = c("R","R","X","X","X","X","X","X","B","R","R","R","X","X","X"),
    Group = c(0,0,0,1,1,0,0,0,0,0,2,2,3,3,3)
  )

nCode <-  myDF1 %>%
  group_by(Name) %>%
  mutate(nmCnt = row_number()) %>%
  ungroup() %>%
  mutate(seqBase = ifelse(Group == 0 | Group != lag(Group), nmCnt,0)) %>%
  mutate(seqBase = na_if(seqBase, 0)) %>%
  group_by(Name) %>%
  fill(seqBase) %>%
  mutate(seqBase = match(seqBase, unique(seqBase))) %>%
  ungroup %>%
  mutate(grpRnk = ifelse(Group > 0, sapply(1:n(), function(x) sum(Name[1:x]==Name[x] & Group[1:x] == Group[x])),0))

loopCntr <- nrow(unique(myDF1[myDF1$Group!=0,]))

for(i in 1:1) {
  
  concat_curnt <- str_c("concat_",i)
  concat_prior <- str_c("concat_",i-1)
 
  nCode <- if(i==1){
    nCode %>% mutate(!! concat_curnt:= as.numeric(paste0(seqBase,".",grpRnk)))} else {
      nCode %>% mutate(!! concat_curnt:= as.numeric(paste0(!!rlang::sym(concat_prior),".",grpRnk)))
    }
}

nCode
  • Related