2010-03-17 43 views
13

Tôi có một bộ dữ liệu csv, có kích thước khoảng 10Gb. Tôi muốn tạo biểu đồ từ các cột của chúng. Nhưng nó có vẻ như cách duy nhất để làm điều này trong numpy là lần đầu tiên tải toàn bộ cột vào một mảng numpy và sau đó gọi numpy.histogram trên mảng đó. Điều này tiêu thụ một lượng bộ nhớ không cần thiết.Biểu đồ Numpy của các mảng lớn

Dịch vụ hỗ trợ trực tuyến có hàng loạt không? Tôi hy vọng cho một cái gì đó mà lặp qua dòng csv của tôi bằng đường dây và thùng giá trị khi nó đọc chúng. Bằng cách này, nhiều nhất là một dòng trong bộ nhớ tại một thời điểm.

Sẽ không khó để cuộn của riêng tôi, nhưng tự hỏi nếu ai đó đã phát minh ra bánh xe này.

Trả lời

9

Như bạn đã nói, nó không phải là khó để cuộn của riêng bạn. Bạn sẽ cần phải tự mình thiết lập và sử dụng lại chúng khi bạn lặp lại tệp. Sau đây phải là một điểm khởi đầu tốt đẹp:

import numpy as np 
datamin = -5 
datamax = 5 
numbins = 20 
mybins = np.linspace(datamin, datamax, numbins) 
myhist = np.zeros(numbins-1, dtype='int32') 
for i in range(100): 
    d = np.random.randn(1000,1) 
    htemp, jnk = np.histogram(d, mybins) 
    myhist += htemp 

Tôi đoán hiệu suất sẽ là vấn đề với các tệp lớn như vậy và chi phí gọi biểu đồ trên mỗi dòng có thể quá chậm. @doug's suggestion của một máy phát điện có vẻ như là một cách tốt để giải quyết vấn đề đó.

+0

Giải pháp tốt. Nếu bạn muốn làm cho nó một chút nhanh hơn, bạn có thể làm 'myhist + = htemp' (tôi đoán rằng nó nhanh hơn vì nó cập nhật biểu đồ tại chỗ). – EOL

+0

Cảm ơn @EOL. Tôi quên một số tính năng Python đẹp vì tôi chưa chuyển hoàn toàn từ Octave. Và sau đó có những tính năng nâng cao như máy phát điện mà tôi chưa học. – mtrw

6

Dưới đây là một cách để bin giá trị của bạn trực tiếp:

import numpy as NP 

column_of_values = NP.random.randint(10, 99, 10) 

# set the bin values: 
bins = NP.array([0.0, 20.0, 50.0, 75.0]) 

binned_values = NP.digitize(column_of_values, bins) 

'binned_values' là một mảng chỉ số, có chứa các chỉ số của bin mà mỗi giá trị trong column_of_values ​​thuộc.

'bincount' sẽ cho bạn (rõ ràng) đếm bin:

NP.bincount(binned_values) 

Với kích thước của bộ dữ liệu của bạn, sử dụng NumPy của 'loadtxt' để xây dựng một máy phát điện, có thể hữu ích:

data_array = NP.loadtxt(data_file.txt, delimiter=",") 
def fnx() : 
    for i in range(0, data_array.shape[1]) : 
    yield dx[:,i] 
+3

Nhưng sẽ không loadtxt tải toàn bộ tệp trong bộ nhớ trước? Đó chính là vấn đề tôi muốn tránh. –

2

binning với phát (bộ dữ liệu lớn; thùng chiều rộng cố định; nổi dữ liệu)

Nếu bạn biết chiều rộng của thùng mong muốn của bạn trước thời hạn - ngay cả khi có hàng trăm hoặc hàng ngàn thùng - sau đó tôi nghĩ rằng giải pháp của riêng bạn lăn sẽ nhanh (cả viết và chạy). Dưới đây là một số Python rằng giả sử bạn có một iterator cung cấp cho bạn giá trị kế tiếp từ file:

from math import floor 
binwidth = 20 
counts = dict() 
filename = "mydata.csv" 
for val in next_value_from_file(filename): 
    binname = int(floor(val/binwidth)*binwidth) 
    if binname not in counts: 
     counts[binname] = 0 
    counts[binname] += 1 
print counts 

Các giá trị có thể nổi, nhưng điều này là giả sử bạn sử dụng một binwidth integer; bạn có thể cần phải tinh chỉnh điều này một chút nếu bạn muốn sử dụng một băng thông của một số giá trị float.

Đối với next_value_from_file(), như đã đề cập trước đó, bạn có thể muốn viết trình tạo hoặc đối tượng tùy chỉnh với phương thức iter() làm điều này một cách hiệu quả.Các giả cho một máy phát điện như vậy sẽ là thế này:

def next_value_from_file(filename): 
    f = open(filename) 
    for line in f: 
    # parse out from the line the value or values you need 
    val = parse_the_value_from_the_line(line) 
    yield val 

Nếu một đường thẳng cho trước có nhiều giá trị, sau đó hãy chắc parse_the_value_from_the_line() hoặc trả về một danh sách hoặc bản thân là một máy phát điện, và sử dụng giả này:

def next_value_from_file(filename): 
    f = open(filename) 
    for line in f: 
    for val in parse_the_values_from_the_line(line): 
     yield val 
3

binning với một Fenwick Tree(bộ dữ liệu rất lớn; ranh giới phần trăm cần thiết)

tôi đăng một giây một chuyển sang cùng một câu hỏi vì cách tiếp cận này rất khác nhau và giải quyết các vấn đề khác nhau.

Điều gì sẽ xảy ra nếu bạn có một tập dữ liệu VERY lớn (hàng tỷ mẫu) và bạn không biết trước thời hạn ranh giới bin của bạn? Ví dụ: có thể bạn muốn đưa mọi thứ vào các phần tư hoặc số thập phân. Đối với các tập dữ liệu nhỏ, câu trả lời rất dễ: tải dữ liệu vào một mảng, sau đó sắp xếp, sau đó đọc các giá trị tại bất kỳ phần trăm đã cho nào bằng cách nhảy tới chỉ mục phần trăm của đường đi qua mảng.

Đối với bộ dữ liệu lớn có kích thước bộ nhớ để giữ mảng không thực tế (chưa kể thời gian sắp xếp) ... thì hãy xem xét sử dụng cây Fenwick, còn gọi là "Cây lập chỉ mục nhị phân".

Tôi nghĩ chúng chỉ làm việc cho dữ liệu số nguyên dương, vì vậy ít nhất bạn cũng cần phải biết đủ về số liệu của mình để thay đổi (và có thể mở rộng) dữ liệu trước khi bạn xếp nó vào cây Fenwick.

Tôi đã sử dụng điều này để tìm trung bình của một tập dữ liệu mẫu 100 tỷ, trong thời gian hợp lý và giới hạn bộ nhớ rất thoải mái. (Xem xét sử dụng máy phát điện để mở và đọc các tập tin, như mỗi câu trả lời khác của tôi, đó là vẫn còn có ích.)

Thông tin thêm về Fenwick Trees:

+0

Đếm là độc lập với thứ tự và không yêu cầu tải tất cả dữ liệu cùng một lúc vào một mảng hoặc sắp xếp nó. – rafaelvalle

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