Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dplyr rename a column, by column index?

The following code renames first column in the data set:

require(dplyr)    
mtcars %>%
        setNames(c("RenamedColumn", names(.)[2:length(names(.))]))

Desired results:

                    RenamedColumn cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4                    21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag                21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710                   22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1

Would it be possible to arrive at the same result using rename and column index?

This:

mtcars %>%
    rename(1 = "ChangedNameAgain")

will fail:

Error in source("~/.active-rstudio-document", echo = TRUE) : 
  ~/.active-rstudio-document:7:14: unexpected '='
6: mtcars %>%
7:     rename(1 =
                ^

Similarly trying to use rename_ or .[[1]] as column reference will return an error.

like image 800
Konrad Avatar asked Mar 13 '17 17:03

Konrad


People also ask

How do I rename a column in a DataFrame by index?

You can rename pandas DataFrame column name by index (position) using rename() method or by assigning column name to df. columns. values[index] .

How do I rename a column in R using dplyr?

To rename a column in R you can use the rename() function from dplyr. For example, if you want to rename the column “A” to “B”, again, you can run the following code: rename(dataframe, B = A) .

How do I rename multiple columns in dplyr?

To change multiple column names by name and by index use rename() function of the dplyr package and to rename by just name use setnames() from data. table . From R base functionality, we have colnames() and names() functions that can be used to rename a data frame column by a single index or name.

How do I rename a specific column in R?

colnames() method in R is used to rename and replace the column names of the data frame in R. The columns of the data frame can be renamed by specifying the new column names as a vector. The new name replaces the corresponding old name of the column in the data frame.

How to rename a column in a data frame?

A column of a data frame can be changed using the position it is in known as its index. Just by the use of index a column can be renamed. This article discusses all such possible methods.

How to rename a column in dplyr?

rename () function from dplyr takes a syntax rename (new_column_name = old_column_name) to change the column from old to a new name. The following example renames the column from id to c1.

How do you rename a column in R with an index?

Rename Column By Index using colnames () colnames () is the method available in R which is used to rename a single column name present in the data frame. Renaming a single column can be done through the column index. We have to specify the index of the column. In R, indexing starts with 1.

How do I select a column by Index in dplyr?

How to Select Columns by Index Using dplyr You can use the following basic syntax in dplyr to select data frame columns by index position: #select columns in specific index positions df %>% select (1, 4, 5) #exclude columns in specific index positions df %>% select (-c (1,2))


3 Answers

As of dplyr 0.7.5, rlang 0.2.1, tidyselect 0.2.4, this simply works:

library(dplyr)  rename(mtcars, ChangedNameAgain = 1)  #                     ChangedNameAgain cyl  disp  hp drat    wt  qsec vs am gear carb # Mazda RX4                       21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 # Mazda RX4 Wag                   21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 # Datsun 710                      22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 # Hornet 4 Drive                  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 # Hornet Sportabout               18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 # ... 

Original answer and edits now obsolete:

The logic of rename() is new_name = old_name, so ChangedNameAgain = 1 would make more sense than 1 = ChangedNameAgain.

I would suggest:

mtcars %>% rename_(ChangedNameAgain = names(.)[1]) #                     ChangedNameAgain cyl  disp  hp drat    wt  qsec vs am gear carb # Mazda RX4                       21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 # Mazda RX4 Wag                   21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 # Datsun 710                      22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 # Hornet 4 Drive                  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 # Hornet Sportabout               18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 # Valiant                         18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 

Edit

I have yet to wrap my head around the new dplyr programming system based on rlang, since versions 0.6/0.7 of dplyr.

The underscore-suffixed version of rename used in my initial answer is now deprecated, and per @jzadra's comment, it didn't work anyway with syntactically problematic names like "foo bar".

Here is my attempt with the new rlang-based Non Standard Evaluation system. Do not hesitate to tell me what I've done wrong, in the comments:

df <- tibble("foo" = 1:2, "bar baz" = letters[1:2])  # # A tibble: 2 x 2 #     foo `bar baz` #   <int>     <chr> # 1     1         a # 2     2         b 

First I try directly with rename() but unfortunately I've got an error. It seems to be a FIXME (or is this FIXME unrelated?) in the source code (I'm using dplyr 0.7.4), so it could work in the future:

df %>% rename(qux = !! quo(names(.)[[2]]))  # Error: Expressions are currently not supported in `rename()` 

(Edit: the error message now (dplyr 0.7.5) reads Error in UseMethod("rename_") : no applicable method for 'rename_' applied to an object of class "function")

(Update 2018-06-14: df %>% rename(qux = !! quo(names(.)[[2]])) now seems to work, still with dplyr 0.7.5, not sure if an underlying package changed).

Here is a workaround with select that works. It doesn't preserve column order like rename though:

df %>% select(qux = !! quo(names(.)[[2]]), everything())  # # A tibble: 2 x 2 #     qux   foo #   <chr> <int> # 1     a     1 # 2     b     2 

And if we want to put it in a function, we'd have to slightly modify it with := to allow unquoting on the left hand side. If we want to be robust to inputs like strings and bare variable names, we have to use the "dark magic" (or so says the vignette) of enquo() and quo_name() (honestly I don't fully understand what it does):

rename_col_by_position <- function(df, position, new_name) {   new_name <- enquo(new_name)   new_name <- quo_name(new_name)   select(df, !! new_name := !! quo(names(df)[[position]]), everything()) } 

This works with new name as a string:

rename_col_by_position(df, 2, "qux")  # # A tibble: 2 x 2 #     qux   foo #   <chr> <int> # 1     a     1 # 2     b     2 

This works with new name as a quosure:

rename_col_by_position(df, 2, quo(qux))  # # A tibble: 2 x 2 #     qux   foo #   <chr> <int> # 1     a     1 # 2     b     2 

This works with new name as a bare name:

rename_col_by_position(df, 2, qux)  # # A tibble: 2 x 2 #     qux   foo #   <chr> <int> # 1     a     1 # 2     b     2 

And even this works:

rename_col_by_position(df, 2, `qux quux`)  # # A tibble: 2 x 2 #   `qux quux`   foo #        <chr> <int> # 1          a     1 # 2          b     2 
like image 164
Aurèle Avatar answered Sep 20 '22 07:09

Aurèle


Here's a couple of alternative solutions that are arguably easier to read because they are not focused around the . reference. select understands column indices, so if you're renaming the first column, you can simply do

mtcars %>% select( RenamedColumn = 1, everything() ) 

However, the issue with using select is that it will reorder columns if you're renaming a column in the middle. To get around the issue, you have to pre-select the columns to the left of the one you're renaming:

## This will rename the 7th column without changing column order mtcars %>% select( 1:6, RenamedColumn = 7, everything() ) 

Another option is to use the new rename_at, which also understand column indices:

## This will also rename the 7th column without changing the order ## Credit for simplifying the second argument: Moody_Mudskipper mtcars %>% rename_at( 7, ~"RenamedColumn" ) 

The ~ is needed because rename_at is quite flexible and can accept functions as its second argument. For example, mtcars %>% rename_at( c(2,4), toupper ) will make the names of the second and fourth columns uppercase.

like image 45
Artem Sokolov Avatar answered Sep 20 '22 07:09

Artem Sokolov


dplyr has superceded rename_at() with rename_with(). You can rename a column by index like this:

library(tidyverse)

mtcars %>% 
  rename_with(.cols = 1, ~"renamed_column")

#>                     renamed_column cyl  disp  hp drat    wt  qsec vs am gear
#> Mazda RX4                    21.0   6 160.0 110 3.90 2.620 16.46  0  1    4
#> Mazda RX4 Wag                21.0   6 160.0 110 3.90 2.875 17.02  0  1    4
#> Datsun 710                   22.8   4 108.0  93 3.85 2.320 18.61  1  1    4
#> Hornet 4 Drive               21.4   6 258.0 110 3.08 3.215 19.44  1  0    3
#> Hornet Sportabout            18.7   8 360.0 175 3.15 3.440 17.02  0  0    3
#> ...

Be sure to include the tilde (~)* before the new column name.

Also note that if you introduce the glue package, you can modify existing column names like this:

library(glue)

mtcars %>% 
  rename_with(.cols = 1, ~glue::glue("renamed_{.}"))
#>                     renamed_mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> Mazda RX4                  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> Mazda RX4 Wag              21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> Datsun 710                 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> Hornet 4 Drive             21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> Hornet Sportabout          18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#> ...

Applying the above approach to multiple columns is just a matter of passing in the column index number range using a colon (:) or multiple indices in a vector using c(); here's a combination of both:

mtcars %>% 
  rename_with(.cols = c(1:3, 5), ~glue::glue("renamed_{.}"))
#>                     renamed_mpg renamed_cyl renamed_disp  hp renamed_drat    wt
#> Mazda RX4                  21.0           6        160.0 110         3.90 2.620
#> Mazda RX4 Wag              21.0           6        160.0 110         3.90 2.875
#> Datsun 710                 22.8           4        108.0  93         3.85 2.320
#> Hornet 4 Drive             21.4           6        258.0 110         3.08 3.215
#> Hornet Sportabout          18.7           8        360.0 175         3.15 3.440
#> ...

And keep in mind that since the . represents the current column name, you can apply string modification functions to it like this:

mtcars %>% 
  rename_with(.cols = c(1:3), 
              ~glue::glue("renamed_{str_replace(.,'mpg','miles_per_gallon')}"))
#>                     renamed_miles_per_gallon renamed_cyl renamed_disp  hp
#> Mazda RX4                               21.0           6        160.0 110
#> Mazda RX4 Wag                           21.0           6        160.0 110
#> Datsun 710                              22.8           4        108.0  93
#> Hornet 4 Drive                          21.4           6        258.0 110
#> Hornet Sportabout                       18.7           8        360.0 175
#> ...

*You can learn more about the ~ and . NSE function shorthand here.

like image 38
phi Avatar answered Sep 19 '22 07:09

phi