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

Time:09-16

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)

CodePudding user response:

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