2012-11-15 37 views
19

Tôi có danh sách tệp. Tôi cũng có một danh sách "tên" mà tôi substr() từ tên tệp thực sự của những tệp này. Tôi muốn thêm một cột mới vào từng tệp trong danh sách. Cột này sẽ chứa phần tử tương ứng trong "tên" được lặp lại nhiều lần số hàng trong tệp.Thêm cột mới vào từng phần tử trong danh sách bảng hoặc khung dữ liệu

Ví dụ:

df1 <- data.frame(x = 1:3, y=letters[1:3]) 
df2 <- data.frame(x = 4:6, y=letters[4:6]) 
filelist <- list(df1,df2) 
ID <- c("1A","IB") 

Mã giả

for(i in length(filelist)){ 

     filelist[i]$SampleID <- rep(ID[i],nrow(filelist[i]) 

    } 

// cơ bản tạo một cột mới trong mỗi dataframes trong filelist, và điền vào cột với các giá trị tương ứng repeted ID

đầu ra của tôi phải như sau:

filelist[1] nên là:

x y SAmpleID 
1 1 a  1A 
2 2 b  1A 
3 3 c  1A 

fileList[2]

x y SampleID 
1 4 d  IB 
2 5 e  IB 
3 6 f  IB 

và vân vân .....

Bất cứ ý tưởng làm thế nào nó có thể được thực hiện.

Trả lời

24

Một giải pháp thay thế là sử dụng cbind, và lợi dụng thực tế là R sẽ recylce giá trị của một ngắn hơn vector.

Ví dụ

x <- df2 # from above 
cbind(x, NewColumn="Singleton") 
# x y NewColumn 
# 1 4 d Singleton 
# 2 5 e Singleton 
# 3 6 f Singleton 

Không có nhu cầu sử dụng của rep. R làm điều đó cho bạn.

therfore, bạn có thể đặt cbind(filelist[[i]], ID[[i]]) trong for loop của bạn hoặc như @Sven chỉ ra, bạn có thể sử dụng trình dọn dẹp mapply:

filelist <- mapply(cbind, filelist, "SampleID"=ID, SIMPLIFY=F) 
+4

Cảm ơn bạn rất nhiều vì sự giúp đỡ và cách tiếp cận đặc biệt của bạn. Vòng lặp for, mapply() và cbind tất cả các công việc giống như một sự quyến rũ. Mặt của nó để học một ngôn ngữ như thế này và tôi học một cái gì đó mới mỗi khi tôi đặt ra một câu hỏi trên diễn đàn này. Tôi xin lỗi tôi không thể viết trước đó để bày tỏ lòng biết ơn và sự đánh giá cao của tôi. Cảm ơn – user1079898

16

Đây là một phiên bản sửa chữa của vòng lặp của bạn:

for(i in seq_along(filelist)){ 

    filelist[[i]]$SampleID <- rep(ID[i],nrow(filelist[[i]])) 

} 

Có 3 vấn đề:

  • Một thức ) đã mất tích sau khi lệnh trong cơ thể.
  • Các yếu tố của danh sách được truy cập bởi [[, không phải bởi [. [ trả về một danh sách độ dài một. [[ chỉ trả về phần tử.
  • length(filelist) chỉ là một giá trị, vì vậy vòng lặp chỉ chạy cho phần tử cuối cùng của danh sách. Tôi đã thay thế nó bằng seq_along(filelist).

Một cách tiếp cận hiệu quả hơn là sử dụng mapply cho nhiệm vụ:

mapply(function(x, y) "[<-"(x, "SampleID", value = y) , 
     filelist, ID, SIMPLIFY = FALSE) 
+12

Bạn không thực sự cần sự vô danh trong 'mapply'. '' mapply ('[<-', filelist, 'sampleID', giá trị = ID, SIMPLIFY = FALSE) '' sẽ hoạt động – mnel

+0

@mnel +1 Ý tưởng tuyệt vời, cảm ơn bạn. –

+0

Tôi cũng chấp nhận câu trả lời của bạn. Tôi nghĩ bạn có thể chấp nhận hai câu trả lời vì tất cả chúng đều rất hữu ích. Tôi xin lỗi nhưng tôi không có ý xúc phạm bạn bằng bất kỳ cách nào. Trên thực tế cho vòng lặp là tuyệt vời và giải thích hữu ích nhất. Cảm ơn bạn rất nhiều! – user1079898

1

Một cách khéo léo:

library(plyr) 

names(filelist) <- ID 
result <- ldply(filelist, data.frame) 
Các vấn đề liên quan