2015-11-06 21 views
5

Tôi đang cố gắng sử dụng lapply trên danh sách các khung dữ liệu; nhưng thất bại trong việc truyền các tham số một cách chính xác (tôi nghĩ).Sử dụng lapply để thay đổi tên cột của danh sách khung dữ liệu

Danh sách khung dữ liệu:

df1 <- data.frame(A = 1:10, B= 11:20) 
df2 <- data.frame(A = 21:30, B = 31:40) 

listDF <- list(df1, df2,df3) #multiple data frames w. way less columns than the length of vector todos 

Vector với tên cột:

todos <-c('col1','col2', ......'colN') 

Tôi muốn thay đổi tên cột bằng lapply:

lapply (listDF, function(x) { colnames(x)[2:length(x)] <-todos[1:length(x)-1] } ) 

nhưng doesn này 't thay đổi tên ở tất cả. Tôi không đi qua các khung dữ liệu, nhưng cái gì khác? Tôi chỉ muốn thay đổi tên, không trả lại kết quả cho một đối tượng mới.

Xin cảm ơn trước, tr.

+0

sẽ không làm việc vì gọi điện thoại * R bằng giá trị * – jogo

+1

Chỉ cần thêm một 'x' đến cuối 'lapply (listDF, function (x) {colnames (x) [2: chiều dài (x)] < -todos [1: length (x) -1]; x}) '. Hàm của bạn như được viết không có giá trị trả về. –

+1

Không liên quan đến câu hỏi, nhưng tôi đoán rằng '1: length (x) -1' là một lỗi phổ biến (đôi khi không có hại). Dòng bên phải là '1: (length (x) -1)' (ưu tiên phần mềm!) – nicola

Trả lời

11

Bạn cũng có thể sử dụng setNames nếu bạn muốn thay thế tất cả các cột

df1 <- data.frame(A = 1:10, B= 11:20) 
df2 <- data.frame(A = 21:30, B = 31:40) 

listDF <- list(df1, df2) 
new_col_name <- c("C", "D") 

lapply(listDF, setNames, nm = new_col_name) 
## [[1]] 
##  C D 
## 1 1 11 
## 2 2 12 
## 3 3 13 
## 4 4 14 
## 5 5 15 
## 6 6 16 
## 7 7 17 
## 8 8 18 
## 9 9 19 
## 10 10 20 

## [[2]] 
##  C D 
## 1 21 31 
## 2 22 32 
## 3 23 33 
## 4 24 34 
## 5 25 35 
## 6 26 36 
## 7 27 37 
## 8 28 38 
## 9 29 39 
## 10 30 40 

Nếu bạn cần phải thay thế chỉ là một tập hợp con của tên cột, sau đó bạn có thể sử dụng các giải pháp của @Jogo

lapply(listDF, function(df) { 
    names(df)[-1] <- new_col_name[-ncol(df)] 
    df 
}) 

một điểm cuối cùng, trong R có sự khác biệt giữa a: b - 1 và a: (b - 1)

1:10 - 1 
## [1] 0 1 2 3 4 5 6 7 8 9 

1:(10 - 1) 
## [1] 1 2 3 4 5 6 7 8 9 

EDIT

Nếu bạn muốn thay đổi tên cột của data.frame trong môi trường toàn cầu từ một danh sách, bạn có thể sử dụng list2env nhưng tôi không chắc chắn nó là cách tốt nhất để đạt được muốn bạn muốn. Bạn cũng cần phải sửa đổi danh sách của bạn và sử dụng danh sách được đặt tên, tên phải giống như tên của data.frame bạn cần phải thay thế.

listDF <- list(df1 = df1, df2 = df2) 

new_col_name <- c("C", "D") 

listDF <- lapply(listDF, function(df) { 
    names(df)[-1] <- new_col_name[-ncol(df)] 
    df 
}) 

list2env(listDF, envir = .GlobalEnv) 
str(df1) 
## 'data.frame': 10 obs. of 2 variables: 
## $ A: int 1 2 3 4 5 6 7 8 9 10 
## $ C: int 11 12 13 14 15 16 17 18 19 20 
+0

Kiểm tra kết quả đầu ra so với mã OP. Dòng 'colnames (x) [2: length (x)]' chỉ ra rằng sự thay thế bắt đầu ở cột thứ hai. –

+0

@PierreLafortune Cảm ơn Pierre bạn đã đúng, tôi đã thực hiện một số điều chỉnh – dickoa

+0

Xin lỗi dickoa nhưng lapply chỉ thay đổi tên cột * bên trong * danh sách (vì vậy df1 và df2 vẫn có tên gốc.). Tôi cũng đã thử thêm 'x' từ Pierre nhưng vẫn không làm được điều đó. Tôi chỉ sử dụng danh sách để giữ một danh sách dài các DF, không phải là tôi muốn thay đổi bên trong danh sách. Bất kỳ ý tưởng? cảm ơn – user3310782

1

thử điều này:

lapply (listDF, function(x) { 
    names(x)[-1] <- todos[-length(x)] 
    x 
}) 

bạn sẽ nhận được một danh sách mới với dataframes thay đổi. Nếu bạn muốn thao tác listDF trực tiếp:

for (i in 1:length(listDF)) names(listDF[[i]])[-1] <- todos[-length(listDF[[i]])] 
+0

Cảm ơn jogo nhưng tại sao nó không thay đổi tên cột của khung dữ liệu? Nó chỉ thay đổi tên cột bên trong danh sách, không phải trong DF độc lập. – user3310782

+0

nhưng bạn có thể làm 'listDF <- lapply (...)' – jogo

+0

Chắc chắn, nhưng nếu bạn muốn thay đổi tên cột DF, thì sau đó KHÔNG PHẢI là con đường để đi? – user3310782

Các vấn đề liên quan