2013-08-22 12 views
7

Próbuję zmienić nazwy kolumn wielu data.frame s.Zmiana nazwy kolumn w wielu ramkach danych, R

Aby dać przykład, powiedzmy, że mam listę data.frame s dfA, dfB i dfC. Napisałem funkcję changeNames ustawić odpowiednio nazwy, a następnie wykorzystywane lapply następująco:

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

Jednak to nie działa zgodnie z oczekiwaniami. Wygląda na to, że nie przypisuję nowych nazw do data.frame, a jedynie do tworzenia nowych nazw. Co ja tu robię źle?

Z góry dziękuję!

+0

po 'nazwy linii (x) <-' w swojej funkcji, dodać' return (x) 'lub po prostu' x'. W przeciwnym razie zwracasz tylko "nazwy (x)". – Arun

+0

Dziękuję za odpowiedź Arun! Jeśli zwrócę reklamę (x), otrzymam wydruk dfA, dfB i dfC z nowymi nazwami.Ale jeśli później zobaczę nazwy (dfA), nazwy (dfB) i nazwy (dfC), nadal będą one miały stare nazwy kolumn. Moje ramki danych są również bardzo duże, więc nie jestem zainteresowany ich przeglądaniem. Zmienia tylko nazwy kolumn. – user2706593

+0

'lapply' nie zmienia wejścia. Nie ma tutaj "zmiany przez odniesienie". Wszystko odbywa się na kopii. Musisz przypisać wynik z powrotem. do: 'dfs <- lapply (dfs, ChangeNames)' – Arun

Odpowiedz

12

Są dwie rzeczy tutaj:

  • 1) Należy zwrócić wartość chcesz z funkcji. W przeciwnym razie zwrócona zostanie ostatnia wartość. W twoim przypadku jest to names(x). Zamiast tego powinieneś dodać jako ostatnią linię: return(x) lub po prostu x. Więc twoja funkcja będzie wyglądać następująco:

    ChangeNames <- function(x) { 
        names(x) <- c("A", "B", "C") 
        return(x) 
    } 
    
  • 2) lapply nie zmienia swoich obiektów wejściowych przez odniesienie. Działa na kopii. Musisz więc przypisać wyniki z powrotem. Lub inną alternatywą jest użycie for-loops zamiast lapply:

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

Nawet używając for-loop, nadal będziesz zrobić kopię (bo names(.) <- . robi). Możesz to sprawdzić, używając 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>" 

Jeśli chcesz zmodyfikować poprzez odniesienie, można użyć data.table innych pakietów setnames funkcję:

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>" 

widać, że lokalizacja pamięci df jest odwzorowywany nie uległa zmianie. Nazwy zostały zmodyfikowane przez odniesienie.

+0

Używanie tego jako funkcji do zmiany nazw kolumn w wielu ramkach danych zawartych na takiej liście było niezwykle pomocne. Uogólniłem funkcję, aby wziąć drugi i trzeci argument, i użyłem tego jako danych wejściowych dla 'grep()' do zmiany nazw określonych kolumn we wszystkich moich ramkach danych. – ano

6

Jeśli ramek danych nie znajdowały się na liście, ale tylko w środowisku globalnym, można odwoływać się do nich za pomocą wektora nazw łańcuchów.

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

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

Istnieje prawdopodobnie sposób, aby to uprościć bez konieczności uciekania się do tworzenia tymczasowego zestawu danych, ale nie udało mi się go rozwiązać!

-1

Miałem problem z zaimportowaniem publicznego zestawu danych i konieczności zmiany nazwy każdej ramki danych i zmiany nazwy każdej kolumny w każdej ramce danych, aby przyciąć białe spacje, małe litery i zastąpić wewnętrzne spacje kropkami.

Łącząc powyższe metody got me:

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) 
} 
Powiązane problemy