Home > Mobile >  Add 1 to column names that ends in integer r
Add 1 to column names that ends in integer r

Time:10-27

My problem is quite straightforward, I have a dataframe with many columns, some of them start with q03b_, like this:

ID  ...  q03b_0 q03b_1 q03b_2 ... q03b_14
 1  ...    a      b      c           m

But I need to change the column names to q03b_other_1, q03b_other_2, q03b_other_3, etc (counting from 1 instead of 0). I managed to select the columns with rename_at and add the "other" to the column names, like this:

df  %>% 
  rename_at(vars(matches('q03b_')), list(~ str_replace(., "b_(\\d )", "_other_\\1")))

Which brings a dataframe like this:

ID  ...  q03_other_0 q03_other_1 q03_other_2 ... q03_other_14
 1  ...    a               b          c               m

But I'm struggling to get to the final stage, which would be this:

ID  ...  q03_other_1 q03_other_2 q03_other_3 ... q03_other_15
 1  ...    a                b           c                m

I guess I need to use a combination of as.numeric and as.character, but because of tidy evaluation I'm struggling to find a way to make this work. Any ideas?

Thanks !

CodePudding user response:

With gsubfn:

library(dplyr)
library(readr)
library(gsubfn)

df %>%
  rename_at(vars(matches('q03b_')), 
            list(~ gsubfn("b_\\d $", 
                          ~ paste0("_other_", 
                                   parse_number(x)   1), 
                          .)))

Output

  q03_other_1 q03_other_2 q03_other_3
1           a           b           c

CodePudding user response:

Here is an alternative way using sprintf:

library(dplyr)
library(stringr)
df %>% 
  select(-ID) %>% 
  rename_with(~str_replace(., "[0-9] $", sprintf("%.0f", 1:length(colnames(df))))) %>% 
  rename_with(~str_replace(., "b", "")) %>% 
  bind_cols(ID=df$ID)
  q03_other_1 q03_other_2 q03_other_3 ID
1           a           b           c  1

CodePudding user response:

We can also use

library(dplyr)
library(stringr)
df %>% 
   rename_with(~ str_replace(., "b_\\d $", function(x)
     str_c('_other_', readr::parse_number(x)   1)) , starts_with('q03b_'))
  ID q03_other_1 q03_other_2 q03_other_3
1  1           a           b           c

data

df <- structure(list(ID = 1L, q03b_0 = "a", q03b_1 = "b", q03b_2 = "c"), class = "data.frame", row.names = c(NA, 
-1L))

CodePudding user response:

Try the following:

library(tidyverse)

df <- data.frame(
  stringsAsFactors = FALSE,
                ID = c(1L),
            q03b_0 = c("a"),
            q03b_1 = c("b"),
            q03b_2 = c("c")
      )

names(df)[-1] <- names(df)[-1] %>% 
  str_remove("_.*") %>% 
  paste0("_other_",1:length(.))

df
#>   ID q03b_other_1 q03b_other_2 q03b_other_3
#> 1  1            a            b            c

EDIT: A more general solution:

library(tidyverse)

df <- data.frame(
  stringsAsFactors = FALSE,
                ID = c(1L),
            q03b_0 = c("a"),
            q03b_1 = c("b"),
            q03b_2 = c("c")
      )

names(df)[str_detect(names(df), "^q03b_")] %<>% 
  str_split("_") %>% 
  map_chr(~ paste0(.x[1], "_other_", 1 as.numeric(.x[2])))

df 
#>   ID q03b_other_1 q03b_other_2 q03b_other_3
#> 1  1            a            b            c
  • Related