2013-08-22 20 views
7

Sto tentando di rinominare colonne di più data.frame s.Rinomina colonne in più dataframes, R

per fare un esempio, diciamo che ho una lista di data.frame s dfA, dfB e dfC. Ho scritto una funzione changeNames per impostare i nomi di conseguenza e quindi utilizzato lapply come segue:

dfs <- list(dfA, dfB, dfC) 
ChangeNames <- function(x) { 
    names(x) <- c("A", "B", "C") 
} 
lapply(dfs, ChangeNames) 

Tuttavia, questo non funziona come previsto. Sembra che non stia assegnando i nuovi nomi allo data.frame, ma solo creando i nuovi nomi. Cosa sto facendo di sbagliato qui?

Grazie in anticipo!

+0

Dopo i nomi linea '(x) <-' nella vostra funzione, aggiungere' ritorno (x) 'o semplicemente' x'. Altrimenti, stai restituendo solo 'nomi (x)'. – Arun

+0

Grazie per la tua risposta Arun! Se restituisco (x), otterrò un outprint di dfA, dfB e dfC, con i nuovi nomi.Ma se visualizzo nomi (dfA), nomi (dfB) e nomi (dfC) in seguito, hanno ancora i vecchi nomi di colonna. I miei frame di dati sono anche molto grandi, quindi non sono interessato a visualizzarli. Cambiando solo i nomi delle colonne. – user2706593

+0

'lapply' non modifica l'input. Non c'è nessun "cambiamento di riferimento" che accade qui. Tutto viene fatto su una copia. Dovrai assegnare il risultato indietro. do: 'dfs <- lapply (dfs, ChangeNames)' – Arun

risposta

12

Ci sono due cose qui:

  • 1) Si dovrebbe restituire il valore che volete dal vostro funzione. Altrimenti, verrà restituito l'ultimo valore. Nel tuo caso, è names(x). Quindi, invece, dovresti aggiungere come linea finale, return(x) o semplicemente x. Quindi, la funzione sarà simile:

    ChangeNames <- function(x) { 
        names(x) <- c("A", "B", "C") 
        return(x) 
    } 
    
  • 2) lapply non modifica gli oggetti di ingresso per riferimento. Funziona su una copia. Quindi, dovrai restituire i risultati. O un'altra alternativa è quella di utilizzare for-loops invece di lapply:

    # option 1 
    dfs <- lapply(dfs, ChangeNames) 
    
    # option 2 
    for (i in seq_along(dfs)) { 
        names(dfs[[i]]) <- c("A", "B", "C") 
    } 
    

Anche utilizzando il for-loop, ci si può comunque fare una copia (a causa names(.) <- . fa). È possibile verificare questo utilizzando tracemem.

df <- data.frame(x=1:5, y=6:10, z=11:15) 
tracemem(df) 
# [1] "<0x7f98ec24a480>" 
names(df) <- c("A", "B", "C") 
tracemem(df) 
# [1] "<0x7f98e7f9e318>" 

Se si desidera modificare per riferimento, è possibile utilizzare la funzione setnamesdata.table pacchetto di:

df <- data.frame(x=1:5, y=6:10, z=11:15) 
require(data.table) 
tracemem(df) 
# [1] "<0x7f98ec76d7b0>" 
setnames(df, c("A", "B", "C")) 
tracemem(df) 
# [1] "<0x7f98ec76d7b0>" 

Si vede che la posizione di memoria df è mappata non è cambiato. I nomi sono stati modificati per riferimento.

+0

L'utilizzo di questa funzione per modificare i nomi delle colonne su più frame di dati contenuti in un elenco come questo è stato incredibilmente utile. Ho generalizzato la funzione per prendere un secondo e terzo argomento, e l'ho usato come input per un 'grep()' per cambiare i nomi di colonne specifiche all'interno di tutti i miei frame di dati. – ano

6

Se i dataframes non erano in un elenco ma solo nell'ambiente globale, è possibile fare riferimento ad essi utilizzando un vettore di nomi di stringhe.

dfs <- c("dfA", "dfB", "dfC") 

for(df in dfs) { 
    df.tmp <- get(df) 
    names(df.tmp) <- c("A", "B", "C") 
    assign(df, df.tmp) 
} 

C'è probabilmente un modo per semplificare questo senza dover ricorrere alla creazione di un insieme di dati temporanea, ma non hanno lavorato fuori!

-1

Ho avuto il problema di importare un set di dati pubblici e dover rinominare ogni dataframe e rinominare ogni colonna in ogni dataframe per tagliare gli spazi bianchi, in minuscolo e sostituire gli spazi interni con i punti.

combinando i metodi di cui sopra mi ha fatto:

for (eachdf in dfs) 
    df.tmp <- get(eachdf) 
    for (eachcol in 1:length(df.tmp)) 
     colnames(df.tmp)[eachcol] <- 
     str_trim(str_to_lower(str_replace_all(colnames(df.tmp)[eachcol], " ", "."))) 
     } 
    assign(eachdf, df.tmp) 
} 
Problemi correlati