2015-06-04 11 views
6

Ho la seguente data.frame:Come sostituire data.frame nomi delle colonne con stringa nella tabella di ricerca corrispondente R

set.seed(126) 
df <- data.frame(a=sample(c(1:100, NA), 10), b=sample(1:100, 10), c=sample(1:100, 10), d = c(1:10)) 
    a b c d 
1 18 27 53 1 
2 44 16 66 2 
3 58 47 3 3 
... 

E la seguente tabella di ricerca:

varnames <- data.frame(old = c("a", "b", "c"), new = c("dog", "cat", "mouse")) 
    old new 
1 a dog 
2 b cat 
3 c mouse 

Quello che sono cercando di fare è sostituire la names(df) con il corrispondente varnames$new ... Se un names(df) non è in varnames$old, poi trattenere il colname in df ...

Il data.frame risultante Vorrei tornato sarebbe simile a questa:

dog cat mouse d 
1 57 10 83 1 
2 53 99 94 2 
3 99 60 39 3 
... 

Qualsiasi aiuto apprezzato.

risposta

9

ne dite di usare la funzione

mm <- match(names(df), varnames$old) 
names(df)[!is.na(mm)] <- as.character(varnames$new[na.omit(mm)]) 
head(df) 
# dog cat mouse d 
# 1 65 48 19 1 
# 2 46 15 80 2 
# 3 NA 47 84 3 
# 4 68 34 46 4 
# 5 23 75 42 5 
# 6 92 87 68 6 

match() Se siete interessati, si potrebbe anche utilizzare la funzione dplyrrename()

library(dplyr) 
df %>% rename_(.dots=with(varnames, setNames(as.list(as.character(old)), new))) 

O ancora un'opzione, il pacchetto data.table ha una funzione setnames

library(data.table) 
setnames(df, as.character(varnames$old), as.character(varnames$new)) 
+1

Credo che nel caso in cui 'varnames' non ha mai nomi di colonna che non sono presenti in' df' (proprio come si presume nel vostro 'implementazione setnames', altrimenti non funzionerà), si potrebbe semplificare il vostro primi due linee per solo 'names (df) [match (varnames $ old, names (df))] <- as.character (varnames $ new)'. Bella implementazione di 'setnames' btw. –

+0

@DavidArenburg in realtà la versione 'data.table' di' setnames' non presuppone che tutti i valori siano presenti nel vettore di sostituzione. Tutti i metodi di cui sopra dovrebbero essere equivalenti come scritti. – MrFlick

+0

Quello che intendevo è che se cambierai 'varnames' per dire' varnames <- data.frame (old = c ("l", "b", "c"), new = c ("dog", " cat "," mouse "))', il tuo approccio di base R funzionerà ancora come previsto, mentre 'setnames' fallirà. –

2

Un'altra possibilità è mapvalues() dal pacchetto plyr:

library(plyr) 
names(df) <- mapvalues(names(df), 
          from = varnames$old, 
          to = as.character(varnames$new)) 

Se si utilizza il pacchetto dplyr, è possibile chiamare questo con plyr::mapvalues() in modo da non dover caricare plyr in cima dplyr (che causa problemi).

Problemi correlati