How to append dataframe column names with for-loop iteration count in R?

Viewed 23

This is my first-time trying a for-loop in R. I am trying to append to the looped-over data frame column header names, the loop iteration count as shown below in the image. Columns concat, alloc, merge, reSeq, are generated in the loop and I'd like to change their names to concat_1, alloc_1, merge_1, reSeq_1 for the first loop, etc. Any recommendations for how to do this?

enter image description here

I'm starting very easy, looping only 1 time so I can gently step into this. In my next step I'll expand the loop so that columns are added to the right and similarly sequentially renamed. I did attempt to append to column names in the first mutate under the for-loop in the below code for each reference to concat but it doesn't work: mutate(paste0("concat_",i) = as.numeric... So I imagine the solution will be something like running colnames(...) at the bottom of the loop, etc.

Here's the code with example DF:

library(dplyr)

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

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) {nCode <- nCode %>% 
    mutate(concat = as.numeric(paste0(seqBase,".",grpRnk)))
    
    index <- filter(nCode, Group !=0) %>% 
      select(concat) %>% 
      distinct() %>% 
      mutate(truncInd = trunc(concat)) %>%
      group_by(truncInd) %>% 
      mutate(cumGrp = cur_group_id()) %>%
      ungroup() %>%
      select(-truncInd)
    index <- if(ifelse(loopCntr > 0, min(index$concat), Inf) >= 2){
      rbind(data.frame(concat=c(1),cumGrp=c(1)),index)}else{index}
    
    nCode <- nCode %>%
      mutate(alloc = index$concat[index$cumGrp==1][nmCnt]) %>%
      mutate(merge = ifelse(is.na(alloc),seqBase,alloc)) %>%
      group_by(Name) %>%
      mutate(reSeq = match(trunc(merge), unique(trunc(merge)))) %>%
      mutate(reSeq = (reSeq + round(merge%%1 * 10,0)/10)) %>%
      ungroup()
  } # end for-loop
      
  print.data.frame(nCode)
1 Answers

Perhaps, assign with names<- or setNames or use rename_with at the end of the loop

library(dplyr)
library(stringr)
for(i in 1:1) {nCode <- nCode %>% 
    mutate(concat = as.numeric(paste0(seqBase,".",grpRnk)))
    
    index <- filter(nCode, Group !=0) %>% 
      select(concat) %>% 
      distinct() %>% 
      mutate(truncInd = trunc(concat)) %>%
      group_by(truncInd) %>% 
      mutate(cumGrp = cur_group_id()) %>%
      ungroup() %>%
      select(-truncInd)
    index <- if(ifelse(loopCntr > 0, min(index$concat), Inf) >= 2){
      rbind(data.frame(concat=c(1),cumGrp=c(1)),index)}else{index}
    
    nCode <- nCode %>%
      mutate(alloc = index$concat[index$cumGrp==1][nmCnt]) %>%
      mutate(merge = ifelse(is.na(alloc),seqBase,alloc)) %>%
      group_by(Name) %>%
      mutate(reSeq = match(trunc(merge), unique(trunc(merge)))) %>%
      mutate(reSeq = (reSeq + round(merge%%1 * 10,0)/10)) %>%
      ungroup()
     nCode <- nCode %>%
        rename_with(~ str_c(.x, "_", i), c("concat", "alloc", "merge", "reSeq"))
  } # end for-loop

-output

> nCode
# A tibble: 6 × 9
  Name  Group nmCnt seqBase grpRnk concat_1 alloc_1 merge_1 reSeq_1
  <chr> <dbl> <int>   <int>  <dbl>    <dbl>   <dbl>   <dbl>   <dbl>
1 R         0     1       1      0      1       1.1     1.1     1.1
2 R         0     2       2      0      2       1.2     1.2     1.2
3 B         0     1       1      0      1       1.1     1.1     1.1
4 R         0     3       3      0      3      NA       3       2  
5 X         1     1       1      1      1.1     1.1     1.1     1.1
6 X         1     2       1      2      1.2     1.2     1.2     1.2

Or another option is using := while assignment

...
  mutate(!! paste0("alloc_", i) := index$concat[index$cumGrp==1][nmCnt])%>%
...
Related