2

I have some data such as:

data(iris)

I want to rename the columns such that Species is the Y variable and all other variables are the predictors.

What I have current doesn't give me the result I am looking for.

iris %>%
  select(Species, everything()) %>% # move the Y variable to the "front"
  rename(Y = 1) %>%
  rename_at(vars(2:ncol(.)), ~ paste("X", seq(2:ncol(.)), sep = ""))

Expected output would be colnames:

Y, X1, X2, X3, X4, X5... XN

user113156
  • 6,761
  • 5
  • 35
  • 81
  • `select(iris, Species, everything()) %>% setNames(c("Y", paste0("X", seq_along(colnames(.))[-1]-1)))` – r2evans Sep 27 '19 at 22:07
  • Possible duplicate of [use %>% with replacement functions like colnames()<-](https://stackoverflow.com/questions/28100780/use-with-replacement-functions-like-colnames) – divibisan Sep 27 '19 at 22:24
  • @divibisan that post doesn't deal with creating the names dynamically – camille Sep 27 '19 at 22:37
  • But the asker seems to know how to create the names dynamically – that part of their code works – divibisan Sep 27 '19 at 22:45

4 Answers4

4

What went wrong

The mistake in your code is that it assumes the second . (in the anonymous function) is a tibble, when in fact it's really a character vector. Hence, ncol(.) is inappropriate, and instead should be length(.). Also, no need for seq() and given the output you requested, it should start from 1. In the end, you would have been fine with:

iris %>%
  select(Species, everything()) %>%
  rename(Y = 1) %>%
  rename_at(vars(2:ncol(.)), ~ paste("X", 1:length(.), sep = ""))

The other answers provide alternative ways of expressing this operation. A possibly cleaner version would be

iris %>%
  select(Species, everything()) %>%
  rename(Y = 1) %>%
  rename_with(~ str_c("X", seq_along(.)), -1)
merv
  • 67,214
  • 13
  • 180
  • 245
2

I'm rearranging your steps to avoid having to do any subsetting in creating the names. Instead, give the first column the name X0 knowing you're going to change it to Y.

library(dplyr)

iris %>%
  select(Species, everything()) %>% 
  setNames(paste0("X", seq_along(.) - 1)) %>%
  rename(Y = 1) %>%
  head()
#>        Y  X1  X2  X3  X4
#> 1 setosa 5.1 3.5 1.4 0.2
#> 2 setosa 4.9 3.0 1.4 0.2
#> 3 setosa 4.7 3.2 1.3 0.2
#> 4 setosa 4.6 3.1 1.5 0.2
#> 5 setosa 5.0 3.6 1.4 0.2
#> 6 setosa 5.4 3.9 1.7 0.4
camille
  • 16,432
  • 18
  • 38
  • 60
0

You can set the colnames directly instead of using the sometimes finicky rename functions:

iris %>%
    select(Species, everything()) %>% # move the Y variable to the "front"
    `colnames<-`(c('Y', paste("X", seq(2:ncol(.)), sep = ""))) %>%
    head

       Y  X1  X2  X3  X4
1 setosa 5.1 3.5 1.4 0.2
2 setosa 4.9 3.0 1.4 0.2
3 setosa 4.7 3.2 1.3 0.2
4 setosa 4.6 3.1 1.5 0.2
5 setosa 5.0 3.6 1.4 0.2
6 setosa 5.4 3.9 1.7 0.4

This question explains why `colnames<-` works as a function in the pipe: use %>% with replacement functions like colnames()<-

divibisan
  • 11,659
  • 11
  • 40
  • 58
0

Solution with base r functions:

colnames(iris) <- c("X1", "X2", "X3", "X4", "Y") # rename columns
iris[,c(5,1,2,3,4)] # reorder 

            Y  X1  X2  X3  X4
 #  1  setosa 5.1 3.5 1.4 0.2
 #  2  setosa 4.9 3.0 1.4 0.2
 #  3  setosa 4.7 3.2 1.3 0.2
 #  4  setosa 4.6 3.1 1.5 0.2
 #  5  setosa 5.0 3.6 1.4 0.2
PsychometStats
  • 340
  • 1
  • 7
  • 19