2012-03-23 40 views
8

Tôi có 15 triệu tệp CSV, mỗi tệp có hai cột (số nguyên và dấu phẩy) và từ 5 đến 500 hàng. Mỗi tập tin trông giống như sau:Cách nhanh nhất để nhập hàng triệu tệp trong R?

3453,0.034 
31,0.031 
567,0.456 
... 

Hiện nay, tôi đang lặp lại trên tất cả các tập tin, và sử dụng read.csv() nhập từng tệp vào một danh sách lớn. Đây là phiên bản được đơn giản hóa:

allFileNames = Sys.glob(sprintf("%s/*/*/results/*/*", dir)) 

s$scores = list() 

for (i in 1:length(allFileNames)){ 
     if ((i %% 1000) == 0){ 
      cat(sprintf("%d of %d\n", i, length(allFileNames))) 
     } 

     fileName = allFileNames[i] 
     approachID = getApproachID(fileName) 
     bugID = getBugID(fileName) 

     size = file.info(fileName)$size 
     if (!is.na(size) && size > 0){ # make sure file exists and is not empty 
      tmp = read.csv(fileName, header=F, colClasses=c("integer", "numeric")) 
      colnames(tmp) = c("fileCode", "score") 
      s$scores[[approachID]][[bugID]] = tmp 
     } else { 
      # File does not exist, or is empty. 
      s$scores[[approachID]][[bugID]] = matrix(-1, ncol=2, nrow=1) 
     } 
    } 

tmp = read.csv(fileName, header=F, colClasses=c("integer", "numeric") 

Sau đó, tôi quay lại mỗi ma trận trong danh sách và tính một số chỉ số.

Sau khi bắt đầu quy trình nhập này, có vẻ như sẽ mất khoảng từ 3 đến 5 ngày để hoàn thành. Có cách nào nhanh hơn để thực hiện việc này không?

EDIT: Tôi đã thêm nhiều chi tiết hơn về mã của mình.

+1

thể trùng lặp của [Nhanh chóng đọc bảng rất lớn như dataframes trong R] (http://stackoverflow.com/questions/1727772/quickly-reading-very-large-tables-as-dataframes-in-r) – joran

+1

Bạn đang cố gắng làm gì? Xây dựng một ma trận đơn với tất cả dữ liệu, hoặc đọc và xử lý từng ma trận một cách riêng biệt? –

+0

Điều này có liên quan đến việc tải nhiều tệp cùng một lúc: http://stackoverflow.com/questions/3764292/ – Ben

Trả lời

6

Sử dụng scan (như nhà nước Joshua trong bình luận) có thể là nhanh hơn (3-4 lần):

scan(fileName, what=list(0L,0.0), sep=",", dec=".", quiet=TRUE) 

khác biệt chính là danh sách scan lợi nhuận với hai yếu tố và read.csv lợi nhuận data.frame.

+0

Tôi đã suy nghĩ một cái gì đó như: 'Danh sách [[1]] <- ma trận (quét (tên tệp, what = 0, sep =", "), ncol = 2, byrow = TRUE)'. –

+1

Xin cảm ơn các bạn. Như tôi đã đề cập trong một bình luận khác, bằng cách chuyển sang '' tmp <- matrix (quét (tên tệp, what = 0, sep = ",", quiet = T), ncol = 2, byrow = TRUE) '', mã của tôi là chạy nhanh gấp đôi. Sau khi thực hiện một '' system.time() '', nó xuất hiện rằng phần lớn thời gian cần thiết là trong IO, vì vậy tôi đoán tôi sẽ chỉ phải đợi một chút. – stepthom

7

Tôi không rõ ràng về mục tiêu của bạn, nhưng nếu bạn đang cố gắng để đọc tất cả các file thành một cấu trúc R dữ liệu duy nhất, sau đó tôi thấy hai mối quan tâm thực hiện chính: thời gian truy cập

  1. File - từ thời điểm bạn yêu cầu read.csv, vô số các quá trình phức tạp bắt đầu trên máy của bạn liên quan đến việc xem tệp đó có tồn tại hay không, tìm vị trí của tệp đó trong bộ nhớ hoặc trên đĩa (và đọc dữ liệu vào bộ nhớ, nếu cần), sau đó giải thích dữ liệu trong R. Tôi hy vọng rằng đây sẽ là một sự suy giảm gần như không đổi khi bạn đọc trong hàng triệu tệp.
  2. Phát triển cấu trúc dữ liệu duy nhất của bạn với từng tệp mới được đọc. Mỗi lần bạn muốn thêm một vài hàng vào ma trận của mình, bạn có thể cần phải phân bổ lại một đoạn bộ nhớ có kích thước tương tự để lưu trữ ma trận lớn hơn. Nếu bạn đang phát triển mảng của mình 15 triệu lần, bạn chắc chắn sẽ nhận thấy hiệu suất hoạt động chậm lại ở đây. Với vấn đề này, hiệu suất sẽ dần dần tồi tệ hơn khi bạn đọc nhiều tệp hơn.

Vì vậy, hãy lập một số hồ sơ nhanh và xem thời gian đọc. Nếu chúng chậm dần dần khi bạn đọc nhiều tệp hơn, hãy tập trung vào vấn đề # 2. Nếu nó liên tục chậm, thì hãy lo lắng về vấn đề # 1.

giải pháp Về, tôi muốn nói rằng bạn có thể bắt đầu với hai điều:

  1. Kết hợp các tập tin CSV trong một ngôn ngữ lập trình. Một kịch bản lệnh shell đơn giản có khả năng thực hiện công việc cho bạn nếu bạn chỉ lặp qua các tệp và nối chúng vào một tệp lớn duy nhất. Như Joshua và Richie đề cập bên dưới, bạn có thể tối ưu hóa điều này mà không phải chuyển sang ngôn ngữ khác bằng cách sử dụng các hàm scan() hoặc readlines() hiệu quả hơn.
  2. Kích thước trước cấu trúc dữ liệu thống nhất của bạn. Ví dụ: nếu bạn đang sử dụng ma trận, hãy đặt số hàng thành ~ 15 triệu x 100. Điều đó sẽ đảm bảo rằng bạn chỉ phải tìm phòng trong bộ nhớ cho đối tượng này một lần và phần còn lại của thao tác sẽ chỉ chèn dữ liệu vào ma trận có kích thước trước.

Thêm một số chi tiết khác về mã của bạn (danh sách trông giống như bạn đang sử dụng?) Và chúng tôi có thể hữu ích hơn.

+3

Cũng lưu ý rằng 'quét' thích hợp hơn' read.csv' vì dữ liệu có thể được lưu trữ dưới dạng số. –

+0

Hoặc thậm chí có thể 'readLines' +' writeLines' nếu OP chỉ muốn kết hợp các tệp thành một. –

+0

@ Jeff - Cảm ơn câu trả lời chi tiết này. Tôi không nghĩ rằng tôi có thể kết hợp tất cả các tập tin vào một trong những lớn, bởi vì tôi cần chúng được tách ra để phân tích tiếp theo. (Mỗi tập tin đại diện cho một thực hiện thử nghiệm của tôi.) Đối với preallocating datastructure của tôi, có cách nào để preallocate kích thước của danh sách của tôi ('' s $ score'')? BTW- Tôi không thấy sự chậm chạp trở nên tồi tệ hơn và tệ hơn, vì vậy tôi nghĩ hiệu suất bị chi phối bởi đĩa IO. – stepthom

0

Như Jeff đã đề cập, có một số điều ở đây có thể mất nhiều thời gian. Vấn đề có thể là truy cập tập tin, hoặc đọc trong các tập tin, hoặc hết bộ nhớ khi bạn có 15 triệu khung dữ liệu trong RAM.Để giải quyết vấn đề, botleneck có thể khác nhau tùy thuộc vào thông số kỹ thuật của máy của bạn (ví dụ: ổ cứng chậm sẽ làm chậm đọc trong tệp, thiếu RAM sẽ là vấn đề với số lượng tệp cao). Để tìm ra vấn đề, bạn sẽ phải làm một số hồ sơ.

Thử chỉ đọc trong 10000 tệp để bắt đầu và gọi system.time hoặc, nhiều hơn về mặt tinh thần, sử dụng rbenchmark để xem điều gì cần nhiều thời gian nhất.

Sau đó nhìn vào liên kết Joran của

Quickly reading very large tables as dataframes in R

và xem nếu bất kỳ của kỹ thuật này có giúp bạn.

2

Quy trình làm việc chung này như thế nào? Tuy nhiên, chưa được thử nghiệm.

my.list.of.files <- list.files(pattern = ".txt") # char vector of filenames 
my.data <- sapply(my.list.of.files, FUN = function(x) { 
      # read file using scan, craft the output to two columns 
     }) # result is merged 

#or if you use simplify= FALSE 
my.data <- sapply(my.list.of.files, FUN = function(x) { 
      # read file using scan (or some other method), craft the output to two columns 
     }, simplify = FALSE) #you get a list 
my.data <- do.call("rbind", my.data) 
+0

Tôi biết đây chỉ là một mẫu, nhưng lưu ý rằng nếu bạn có tất cả 15 triệu tệp trong một thư mục, đó cũng có thể là nguyên nhân khác gây ra tai họa hiệu suất của bạn. –

+1

Lưu ý rằng 'sapply' hơi chậm vì R phải làm thêm công việc để tìm ra cách đơn giản hóa đầu ra. Trong gia đình '* apply',' lapply' là nhanh nhất, do đó có thể thích hợp hơn ở đây. – flodel

+0

@ Jeff, đây không phải là điều chúng tôi có thể giải thích. @flodel, ngay cả khi bạn chỉ định 'simplify = FALSE'? –

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