51

After transforming a dataframe, I would like to assign heads/names to the columns based on an existing row. My headers are currently:

row.names   X2  X3  X4  X5  X6  X7  X8  X9  ...

I would like to get rid of that and use the following row as column headers (without having to type them out since I have many).

The only solution I have for this is to export and re-load the data (with header=T).

Dason
  • 60,663
  • 9
  • 131
  • 148
user3166363
  • 765
  • 2
  • 7
  • 7

5 Answers5

69

The key here is to unlist the row first.

colnames(DF) <- as.character(unlist(DF[1,]))
DF = DF[-1, ]
dgisser
  • 142
  • 1
  • 10
Vishnu Jayanand
  • 830
  • 7
  • 11
60

Try this:

colnames(DF) = DF[1, ] # the first row will be the header
DF = DF[-1, ]          # removing the first row.

However, get a look if the data has been properly read. If you data.frame has numeric variables but the first row were characters, all the data has been read as character. To avoid this problem, it's better to save the data and read again with header=TRUE as you suggest. You can also get a look to this question: Reading a CSV file organized horizontally.

Ricardo Oliveros-Ramos
  • 4,322
  • 2
  • 25
  • 42
  • I have to tranform the data after I load it, which converts everything into a character matrix. Wondering if I can convert it back to a numeric dataframe with headers without having to export/re-load.. – user3166363 Jan 07 '14 at 18:55
  • It works if I assign the header before transposing. But now all my numerical values are characters.. looking for an efficient way to convert them into numerical without having to call each columns. thanks – user3166363 Jan 08 '14 at 00:41
  • You can also see this question: http://stackoverflow.com/questions/17288197/r-reading-a-csv-organized-horizontally/17289991#17289991 – Ricardo Oliveros-Ramos Jan 08 '14 at 04:58
  • (I'm sorry I'm not sure how to modify the question above) Question: after transforming a character matrix into a dataframe, I would like the columns to revert to their initial nature (numerical, factors etc.) without having to call them individually. The only option I have found is to export and re-load the data. Thanks – user3166363 Jan 08 '14 at 21:41
  • http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Ricardo Oliveros-Ramos Jan 08 '14 at 23:14
  • I have created a new question: "Column properties in data.frame after being converted to char. matrix (transposed). " – user3166363 Jan 09 '14 at 04:19
5

The cleanest way is use a function of janitor package that is built for exactly this purpose.

janitor::row_to_names(DF,1)

If you want to use any other row than the first one, pass it in the second parameter.

Lazarus Thurston
  • 1,197
  • 15
  • 33
2

Very similar to Vishnu's answer but uses the lapply to map all the data to characters then to assign them as the headers. This is really helpful if your data is imported as factors.

DF[] <- lapply(DF, as.character)
colnames(DF) <- DF[1, ]
DF <- DF[-1 ,]

note that that if you have a lot of numeric data or factors you want you'll need to convert them back. In this case it may make sense to store the character data frame, extract the row you want, and then apply it to the original data frame

tempDF <- DF
tempDF[] <- lapply(DF, as.character)
colnames(DF) <- tempDF[1, ]
DF <- DF[-1 ,]
tempDF <- NULL
blakiseskream
  • 338
  • 4
  • 9
-1

A new answer that uses dplyr and tidyr:

Extracts the desired column names and converts to a list

library(tidyverse)

col_names <- raw_dta %>% 
  slice(2) %>%
  pivot_longer(
    cols = "X2":"X10", # until last named column
    names_to = "old_names",
    values_to = "new_names") %>% 
  pull(new_names)

Removes the incorrect rows and adds the correct column names

dta <- raw_dta %>% 
  slice(-1, -2) %>% # Removes the rows containing new and original names
  set_names(., nm = col_names)

greg_s
  • 134
  • 1
  • 4