This post has been slightly modified from its original form on woodpeckR.
Problem
How do I change the name of just one column in a data frame?
Context
This is a simple one that keeps coming up. Sometimes, whoever put together my data decided to capitalize the first letter of some column names and not others. Sometimes I’ve merged several data frames together and I need to distinguish the columns from each other.
Say my data frame is p8_0 and I’d like to change the column Area to area.
In the past, I’ve done this in one of two ways. Either I change all of the column names at once (if all of them need to be changed), or I use numerical column indexing. The latter makes a lot more sense if I have a lot of columns to deal with, but it means I have to know the number of the column whose name I have to change.
To find this out, I first have to look at all of the column names. Okay, no problem.
# See column names and numerical indicesnames(p8_0)
It’s not that hard to see that Area is the 18th column. But there are a bunch of columns that start with NEAR_TERR_ and NEAR_FOREST_ that would be easy to confuse. And what if I later modify my data cleaning script, insert new columns, and mess up the numerical indexing?
Solution
The first solution I came up with is simple but pretty clunky. At least it solves the problem of numerical indices getting misaligned. And if you mistype the column name or try to change the name of a column that doesn’t exist, it doesn’t throw an error.
# Change "Area" column name to "area"names(p8_0)[names(p8_0) =="Area"] <-"area"
This works well, but it gets annoying if you have more than one column name to change. Every column requires typing names(p8_0) twice, and that adds up to a lot of lines of code.
To no one’s surprise, dplyr has a more elegant solution, using the rename function.
# Load dplyr library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
# Rename variable (new name first) p8_0 <- p8_0 %>%rename(area = Area)
A quick note on rename: somewhat counterintuitively, the new name comes before the old name. General example:
# General syntax for rename #df %>% # rename(newname = oldname)
rename saves a whole bunch of keystrokes and also scales very well to multiple columns.
Let’s say I wanted to change Area and Perimeter to area and perimeter, respectively, and I also wanted to change the rather clunky shoreline_density_index to sdi. And while we’re at it, snagyn, a factor variable that indicates whether a large piece of wood was present at the site (“yes” or “no”), might be clearer as snag_yn, and sinuosity could be shortened to sinu
Without dplyr:
# Change each column name individuallynames(p8_0)[names(p8_0) =="Area"] <-"area"names(p8_0)[names(p8_0) =="Perimeter"] <-"perimeter"names(p8_0)[names(p8_0) =="shoreline_density_index"] <-"sdi"names(p8_0)[names(p8_0) =="snagyn"] <-"snag_yn"names(p8_0)[names(p8_0) =="sinuosity"] <-"sinu"
With dplyr:
# Change any column names you want to, all at oncep8_0 <- p8_0 %>%rename(area = Area, perimeter = Perimeter,sdi = shoreline_density_index, snag_yn = snagyn,sinu = sinuosity)
So pretty. As an added bonus, you’re saved from both quotation marks and the dreaded double equals sign (!!!).
In case anyone was counting, that’s 102 characters vs. 238 (spaces not included). 116 if you include loading dplyr, but you already had it loaded because you’re using it throughout your code, of course.
Outcome
Now I can rename only the columns I want, by name instead of numerical index, without fear of having to change everything if I insert or delete some columns later on.
Resources
More thoughts on changing individual variable names, including a couple other packages if you feel like trying them: https://stackoverflow.com/questions/7531868/how-to-rename-a-single-column-in-a-data-frame