5

I have some data that looks like this:

    country agdp apop
1        US  100  100
2 Australia   50   50

The variable names are agdp and apop, but I would like them to be gdp and pop. My real data has many, many variables that all need that transformation.

And this is what my desired outcome:

 country gdp pop
1        US  100  100
2 Australia   50   50

Reproducible code below:

df <- data.frame(stringsAsFactors=FALSE,
     country = c("US", "Australia"),
        agdp = c(100, 50),
        apop = c(100, 50)

desired_df <- data.frame(stringsAsFactors=FALSE,
     country = c("US", "Australia"),
        gdp = c(100, 50),
        pop = c(100, 50)
  • Possible duplicate https://stackoverflow.com/q/35113553/680068 and https://stackoverflow.com/questions/46954165/rename-a-set-of-columns-in-r-by-position – zx8754 Jun 11 '19 at 07:10

4 Answers4

4

Using regex we can extract everything other than first character and assign the names.

names(df)[-1] <- sub("^.(.*)$", "\\1", names(df)[-1])

df
#    country gdp pop
#1        US 100 100
#2 Australia  50  50
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
3

One dplyr possibility could be:

df %>%
 rename_at(2:length(.), list(~ substr(., 2, nchar(.))))

    country gdp pop
1        US 100 100
2 Australia  50  50

The same with base R:

names(df)[-1] <- substr(names(df)[-1], 2, nchar(names(df)[-1]))
tmfmnk
  • 38,881
  • 4
  • 47
  • 67
3

Here is one approach

library(stringr)

names(df)[-1] = str_sub(names(df)[-1], 2)
Sotos
  • 51,121
  • 6
  • 32
  • 66
Theo
  • 575
  • 3
  • 8
  • Adding to this, you could swap out `str_sub` with `substring` if you wanted to use a base function. – Andrew Jun 11 '19 at 12:13
1

One could also do:

Purely base(can use setdiff or %in% to "automate" selection.):

sapply(names(df), function(x) ifelse(x=="country",x,substring(x,2,nchar(x))))

Less elegant with tidyverse since rename_at has been shown:

names(df)<-unlist(names(df) %>% 
  map(.,function(x) ifelse(x=="country",x,substring(x,2,nchar(x)))))
NelsonGon
  • 13,015
  • 7
  • 27
  • 57