2014-05-25 26 views
5

Tôi có tệp CSV 12 GB. Tôi hy vọng sẽ trích xuất chỉ một số cột từ dữ liệu này và sau đó viết một CSV mới mà hy vọng tôi có thể tải vào R để phân tích.Sử dụng Python để phân tích cú pháp 12GB CSV

Sự cố là tôi gặp phải lỗi bộ nhớ khi cố gắng tải toàn bộ danh sách cùng một lúc trước khi viết tệp CSV mới. Làm cách nào để phân tích cú pháp hàng dữ liệu theo hàng và sau đó tạo đầu ra CSV?

Dưới đây là những gì tôi có cho đến nay:

import pandas 

colnames = ['contributor name', 'recipient name', 'recipient party', 'contributor cfscore', 'candidate cfscore', 'amount'] 

DATA = pandas.read_csv('pathname\filename.csv', names=colnames) 
DATA.to_csv(''pathname\filename.csv', cols = colnames) 
+1

Có bạn nhìn vào csvkit? Tôi không biết nó hiệu quả hay tốc độ như thế nào. http://csvkit.readthedocs.org/en/0.7.3/ – A5C1D2H2I1M1N2O1R2T1

+0

Bạn lấy tệp đó ở đâu? – dawg

+0

Dùng thử [Google CRUSH Tools] (https://code.google.com/p/crush-tools/). Bộ công cụ đó có một mảng rộng các thói quen thao tác dữ liệu sẽ cho phép bạn cắt, xúc xắc và thậm chí làm một số tập hợp sơ bộ để có được dữ liệu thành một kích thước dễ quản lý hơn. Ngoài ra, nếu bạn có thể lấy dữ liệu vào một cơ sở dữ liệu đơn giản, 'dplyr' có thể là một lựa chọn tuyệt vời cho việc crunching dữ liệu vì nó rất có thể sẽ không ăn hết bộ nhớ của bạn. – hrbrmstr

Trả lời

5

Bạn có thể sử dụng các mô-đun csv để xử lý các line-by-line tập tin. Một cái gì đó như thế này có thể làm việc:

import csv 
infname = "csv.csv" 
outfname = "csv_stripped.csv" 
cols = ["col1", "col2", "col3"] 
with open(infname) as inf, open(outfname, 'w+') as outf: 
    reader = csv.DictReader(inf) 
    writer = csv.DictWriter(outf, cols, extrasaction='ignore') 
    writer.writeheader() 
    for line in reader: 
     writer.writerow(line) 

Để tham khảo:

+0

@ user3342483 Có lẽ bạn đã có lỗi ở đâu đó (có thể là tên cột hoặc dấu phân cách?). Tôi vừa tạo ra một bài kiểm tra đơn giản, nó làm việc cho tôi. – moooeeeep

+0

Xin lỗi, tôi đã vô tình xóa nhận xét cuối cùng của tôi. Tôi nghĩ rằng không gian trong tên col của tôi đang ném mọi thứ ra. – StanO

+0

Đúng, cố định tên cột và nó hoạt động như một sự quyến rũ! Cảm ơn!!!! – StanO

-1

Hãy thử điều này:

file = open("csv.csv", "r") 
    for line in file: 
     print(line) 

Nó sẽ không tải toàn bộ tập tin vào bộ nhớ, nó phân tích từng dòng.

+0

'cho dòng trong tệp' nên đọc một dòng tại một thời điểm, mà không tải tất cả trong bộ nhớ – M4rtini

+0

Python tải tệp khi bạn làm' readlines() '. Lặp lại các tập tin ('cho dòng trong tập tin: in (dòng)') sẽ không tải toàn bộ tập tin vào bộ nhớ, và có thể trong thực tế làm việc với các dòng vô hạn. –

+0

@AaronHall đã sửa bài đăng, không nhận ra 'cho dòng trong dòng' sẽ không thực sự tải toàn bộ tệp vào bộ nhớ. – RydallCooper

7

Trong R, bạn có thể sử dụng chức năng fread từ phổ biến data.table package.

Bạn có thể sử dụng đối số drop= để chỉ định các cột không được đọc - không có bộ nhớ nào được cấp cho chúng và chúng không được đọc chút nào. Hoặc select= các cột bạn muốn giữ lại, nếu điều đó thuận tiện hơn. fread có thể đọc tệp csv rất, rất nhanh chóng.

Nếu bạn đang xử lý nhiều dữ liệu này, có thể bạn sẽ muốn tự làm quen với gói data.table.


Ngoài ra, ?read.csv.sql từ sqldf package cho biết sẽ

Đọc một tập tin vào R lọc nó với một câu lệnh SQL. Chỉ phần được lọc được xử lý bằng R sao cho các tệp lớn hơn R có thể xử lý khác có thể được cung cấp.

Dưới đây là ví dụ:

write.csv(iris, "iris.csv", quote = FALSE, row.names = FALSE) 
iris2 <- read.csv.sql("iris.csv", 
         sql="select * from file where Species = 'setosa' ") 
+0

Cảm ơn GSee. Tôi đã thử bằng cách sử dụng fread như bạn đã mô tả trước khi đăng bài này, nhưng sau khoảng 25 phút hoặc lâu hơn, sẽ nhận được một lỗi liên quan đến các seperators ... – StanO

+0

@ user3342483 có thể [lỗi này] (http://stackoverflow.com/questions/23833294/ dữ liệu-tablefread-không-như-thiếu-giá trị-in-first-cột) là cắn. : (Thật tuyệt nếu bạn có thể chạy lại nó với 'verbose = TRUE' và gửi kết quả đầu ra vào danh sách dữ liệu trợ giúp. Hoặc nếu tệp có sẵn trực tuyến và bạn có thể cung cấp liên kết, nó sẽ giúp gỡ lỗi. – GSee

+0

Các tập tin có sẵn tại liên kết này, (được cảnh báo, đó là một 2GB): https://dl.dropboxusercontent.com/u/2047562/contribDB_2012.zip Lỗi R cho tôi là: Lỗi trong fread (" ~/BonicaIdeology/contribDB_2012.csv ", verbose = T, chọn = c (" tên cộng tác viên ",: Đúng là eep (',') nhưng ' ' kết thúc trường 20 trên dòng 35265 khi đọc dữ liệu: 2012," e: ind: 2012: 32748445 " , "15", 75, "2011-09-30", 4185397934, "arbitter, daniel ss", "arbitter", "daniel s", "s", "", "", "daniel ss", "Tôi "," M "," 14871 lakewood dr "," plymouth "," MI ", 481702694," manager, core veh dyn – StanO

1

Đọc tất cả dữ liệu vào bộ nhớ đầu tiên không phải là một ý tưởng tốt.

Có hai cách để xử lý các tệp dữ liệu lớn như vậy.

  1. Phát mỗi dòng, chọn thông tin liên quan và loại bỏ phần còn lại cho đến EOF. (xem xml parser)

  2. Phát trực tuyến mỗi dòng và ghi toàn bộ dữ liệu vào một định dạng tốt hơn cho phép bạn dễ dàng truy cập thông tin liên quan. Ví dụ.pytables

1

Nếu bạn có một hàm filter_row mà trở Đúng khi bạn muốn giữ hàng, bạn có thể sử dụng:

with open('input.csv') as inp: 
    with open('output.csv', 'w') as outp: 
     for line in inp: 
      if filter_row(line): 
       outp.write(line) 
2

Bạn không cần python hoặc bất kỳ gói R thêm để làm điều này . Bạn có thể sử dụng đối số colClasses với dữ liệu đầu vào trong R để chỉ đọc trong các cột nhất định. Cung cấp cho một cột một giá trị colClasses của "NULL" để ngăn không cho nó được tải trong khi nhập.

Ví dụ cho một tập tin ("myfile.csv") với 3 cột, nếu là người đầu tiên phải được coi là character, thứ ba phải được coi là integer, và lần thứ hai nên được bỏ qua:

read.csv("myfile.csv", colClasses=c("character", "NULL", "integer")) 

Phương pháp này yêu cầu bạn chỉ định các lớp cho mỗi cột trong tệp của bạn.

Bạn cũng nên đọc lời khuyên về cách sử dụng bộ nhớ tại http://stat.ethz.ch/R-manual/R-devel/library/utils/html/read.table.html nếu bạn có nhiều hàng.

+0

Về mặt kỹ thuật, điều này có thể làm việc, nhưng hiệu suất của read.csv trên một tệp 12GB chắc chắn sẽ là một vấn đề. –

+0

Đúng, điều này sẽ nhanh hơn việc đọc toàn bộ tệp mà không có "NULL", nhưng vẫn còn khá chậm. – ping

0

Bạn có thể đạt được điều này bằng cách sử dụng R và JDBC. Hãy tạo một tệp csv mẫu.

write.table(x=mtcars, file="mtcars.csv", sep=",", row.names=F, col.names=T) # create example csv file 

Tải xuống và lưu trình điều khiển JDBC CSV từ liên kết này: http://sourceforge.net/projects/csvjdbc/files/latest/download rồi thiết lập trình điều khiển.

> library(RJDBC) 

> path.to.jdbc.driver <- "jdbc//csvjdbc-1.0-18.jar" 
> drv <- JDBC("org.relique.jdbc.csv.CsvDriver", path.to.jdbc.driver) 
> conn <- dbConnect(drv, sprintf("jdbc:relique:csv:%s", getwd())) # replace getwd() with location of csv file 

Bây giờ bạn có thể soạn một truy vấn và chọn các cột mà bạn cần và nếu cần, thêm một mệnh đề where để lọc dữ liệu để chỉ chọn hàng nơi thiết bị có giá trị 5:

> dbGetQuery(conn, "select mpg, cyl, gear from mtcars where gear = '5'") 
    mpg cyl gear 
1 26 4 5 
2 30.4 4 5 
3 15.8 8 5 
4 19.7 6 5 
5 15 8 5 
Các vấn đề liên quan