5

I have two data frames. I have a list of column names in a data frame NAME. I then have another data frame DF where the column name is corresponded to data frame NAME in the next column. I need to replace these names to the column names in DF.

DF:
        A   B   C   D   E
 H001   947 95  10  10  678
 H002   647 40  10  10  806
 H003   840 20  99  53  21
 H004   105 10  97  12  44
 H005   595 59  76  76  67

NAME:
Name Real.name
A    Pete
B    May
C    Jon
D    Paul
E    Emma
F    Fuchs
G    George

Desired output:
        Pete May    Jon Paul Emma
 H001   947  95     10  10   678
 H002   647  40     10  10   806
 H003   840  20     99  53   21
 H004   105  10     97  12   44
 H005   595  59     76  76   67
4
  • try sapply(colnames(DF),function(x) grepl(x,Name$Real.name)) Commented Aug 10, 2016 at 13:20
  • 2
    Have you taken a look at ?match Commented Aug 10, 2016 at 13:20
  • @Osssan your regex is very fragile. Try anchoring with ?paste Commented Aug 10, 2016 at 13:23
  • I had the same question years ago. There's a few methods to deal with this in this thread... stat.ethz.ch/pipermail/r-help/2007-September/140298.html Commented Aug 10, 2016 at 14:18

3 Answers 3

12

How about something like this?

Edit: A better alternative as suggested by @PierreLafortune:

names(df) <- name$Real.name[match(names(df), name$Name)]

The original approach:

names(df)<-merge(data.frame(Name=names(df)),name,all.x=T)[,"Real.name"]

df
     Pete May Jon Paul Emma
H001  947  95  10   10  678
H002  647  40  10   10  806
H003  840  20  99   53   21
H004  105  10  97   12   44
H005  595  59  76   76   67

Data:

df <- structure(list(A = c(947L, 647L, 840L, 105L, 595L), B = c(95L, 
40L, 20L, 10L, 59L), C = c(10L, 10L, 99L, 97L, 76L), D = c(10L, 
10L, 53L, 12L, 76L), E = c(678L, 806L, 21L, 44L, 67L)), .Names = c("A", 
"B", "C", "D", "E"), class = "data.frame", row.names = c("H001", 
"H002", "H003", "H004", "H005"))

name <- structure(list(Name = structure(1:7, .Label = c("A", "B", "C", 
"D", "E", "F", "G"), class = "factor"), Real.name = structure(c(7L, 
5L, 4L, 6L, 1L, 2L, 3L), .Label = c("Emma", "Fuchs", "George", 
"Jon", "May", "Paul", "Pete"), class = "factor")), .Names = c("Name", 
"Real.name"), class = "data.frame", row.names = c(NA, -7L))
Sign up to request clarification or add additional context in comments.

4 Comments

No need to slow down to construct a new data frame when NAME has the mapping in place.
@PierreLafortune sorry, I'm not following - are you suggesting to not create a data.frame and still use a merge? Isn't names(df) just a vector?
You can avoid merge and use the fact that the names are already mapped to the new values names(DF) <- NAME$Real.name[match(names(DF), NAME$Name)]
Oh ok - yes that is a better approach. I updated my answer. Thanks!
4

This can also be done with dplyr

library(dplyr)

df <- df %>%
      rename_at(as.vector(na.omit(name$Name[match(names(df), name$Name)])), 
               ~as.vector(na.omit(name$Real.name[match(names(df), name$Name)])))

Comments

2

There are probably many solutions. I would use plyr::mapvalues

names(DF) <- plyr::mapvalues(names(DF), from = NAME$Name, to = NAME$Real.name)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.