2013-08-22 69 views
7

我在嘗試重命名多個data.frame s的列。重命名多個數據框中的列,R

舉一個例子,假設我有一個data.frame s dfA,dfBdfC的列表。我寫了一個函數changeNames相應地設置名稱,然後使用lapply如下:

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

不過,這並不會達到預期效果。看起來我並沒有將新名稱分配給data.frame,而只是創建新名稱。我在這裏做錯了什麼?

預先感謝您!

+0

後行'名稱(X)< - '你的功能,加上'回報(X)'或'簡單x'。否則,你只是返回'names(x)'。 – Arun

+0

謝謝你的回覆阿倫!如果我廣告返回(x),我將得到dfA,dfB和dfC的外印,並帶有新名稱。但是如果我以後查看名稱(dfA),名稱(dfB)和名稱(dfC),它們仍然具有舊的列名稱。我的數據框也非常大,所以我不想查看它們。只更改那裏的列名稱。 – user2706593

+0

'lapply'不會修改輸入。這裏沒有「引用改變」。一切都在副本上完成。你必須重新分配結果。 do:'dfs < - lapply(dfs,ChangeNames)' – Arun

回答

12

這裏有兩件事情:

  • 1)您應返回從功能所需的值。否則,最後的值將被返回。在你的情況下,這是names(x)。所以,你應該添加最後一行,return(x)或者簡單的x。所以,你的函數看起來像:

    ChangeNames <- function(x) { 
        names(x) <- c("A", "B", "C") 
        return(x) 
    } 
    
  • 2)lapply不參照修改您的輸入對象。它在一個副本上工作。所以,你必須重新分配結果。或者另一種選擇是使用for-loops而不是lapply

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

即使使用for-loop,你還是會做一個副本(因爲names(.) <- .一樣)。您可以使用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>" 

如果你想通過參考修改,你可以使用data.table封裝的setnames功能:

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

您將看到該內存位置df映射到沒有改變。這些名稱已經被引用修改。

+0

使用這個功能來改變列表中包含的多個數據幀的列名是非常有用的。我將這個函數推廣到第二個和第三個參數,並將其用作'grep()'的輸入來更改我的所有數據框中特定列的名稱。 – ano

6

如果數據框不在列表中,而只在全局環境中,則可以使用字符串名稱向量來引用它們。

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

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

有可能是爲了簡化而不必訴諸於創建臨時數據集的方式,但我還沒有算出來!

-1

我遇到了導入公共數據集並重命名每個數據框的問題,並重命名每個數據框中的每列以修剪空格,小寫,並用句點替換內部空格。

結合上面的方法讓我:

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) 
}