2012-09-22 5 views
5

私の主な目標は、フロートの巨大な行列からメジアン(列単位)を計算することです。例:Python - ファイルから列イテレータを取得する(ファイル全体を読むことなく)

a = numpy.array(([1,1,3,2,7],[4,5,8,2,3],[1,6,9,3,2])) 

numpy.median(a, axis=0) 

Out[38]: array([ 1., 5., 8., 2., 3.]) 

マトリックスは、Pythonメモリ(〜5件のテラバイト)に収まるには大きすぎるので、私はcsvファイルに保管してください。 だから私は各列を実行し、中央値を計算したいと思います。

ファイル全体を読み取らずに列イテレータを取得する方法はありますか?

マトリックスの中央値を計算する他のアイデアも良いでしょう。ありがとうございました!

+2

参照:http://stackoverflow.com/questions/1053928/python-numpy-very-large-matrices –

答えて

1

N個の空のファイルを各列に1つずつ初期化することでこれを行います。行列を一度に1行ずつ読み込み、各列のエントリを正しいファイルに送ります。行列全体を処理したら、各ファイルの中央値を順番に計算して戻します。

これは基本的にファイルシステムを使用して行列転置を行います。転置後、各行の中央値を計算するのは簡単です。あなたは(あなたができる暗示するように見える)メモリに各列を収めることができた場合は

+1

ご返信ありがとうございます!私の行列サイズは〜5テラバイトですが、私はこれを行うのに十分な記憶域がないのではないかと心配しています:( – dbaron

3

、これは動作するはずです:

これは、我々が持っているどのように多くの列を見つけることによって動作します
import itertools 
import csv 

def columns(file_name): 
    with open(file_name) as file: 
     data = csv.reader(file) 
     columns = len(next(data)) 
    for column in range(columns): 
     with open(file_name) as file: 
      data = csv.reader(file) 
      yield [row[column] for row in data] 

は、そのファイルをループ現在の列の項目を各行から取り出します。これは、たいてい、カラムのサイズとメモリの行のサイズを同時に使用していることを意味します。それはかなり単純なジェネレータです。ファイルをループしたときにイテレータを使い果たすので、ファイルを再オープンしなければならないことに注意してください。

+0

ファイルを再オープンしても問題がなければ、forループの外側に 'with'を移動して' file.seek 0) 'inside。 –

+0

@MuMindこれは何度も何度も再オープンする良い選択肢です。何らかの理由でファイル名がなければファイルオブジェクトを渡すこともできます。 –

0

bucketsortを使用すると、ディスク上の各列をすべてメモリに読み込まずに並べ替えることができます。次に、中央値を選択するだけです。

または、セントラルを選択する前に、UNIX awkおよびsortコマンドを使用して列を分割して並べ替えることができます。

1

おそらくあなたが誤解していない限り、あなたがcsvファイルで求めていることを行う直接的な方法はありません。問題は、ファイルが固定幅の行を持つように特別に設計されていない限り、すべてのファイルに「列」がある意味のある意味がないことです。 CSVファイルは一般にそのようには設計されていません。ディスク上では、これらは巨大な文字列に過ぎません。

>>> import csv 
>>> with open('foo.csv', 'wb') as f: 
...  writer = csv.writer(f) 
...  for i in range(0, 100, 10): 
...   writer.writerow(range(i, i + 10)) 
... 
>>> with open('foo.csv', 'r') as f: 
...  f.read() 
... 
'0,1,2,3,4,5,6,7,8,9\r\n10,11,12,13,14,15,16,17,18,19\r\n20..(output truncated).. 

ご覧のとおり、列フィールドは予測できません。 2番目の列はインデックス2から開始しますが、次の行では列の幅が1増加し、配置が解除されます。入力の長さが変わるとこれはさらに悪化します。結論は、csvリーダーがあなたが使用していないデータを投げ捨てて、ファイル全体を読む必要があるということです。 (あなたが気にしないなら、それは答えです - 使用しないデータを投げ捨てて、行ごとにファイル全体を読んでください)

スペースを無駄にしていないことを知っていればあなたのデータのどれも固定幅よりも長くない場合は、固定幅のフィールドを持つファイルを作成し、オフセットを使ってそれを探し出すことができます。しかし、いったんそれをやったら、実際のデータベースを使い始めることもできます。 PyTablesは、数が少ない配列を格納するための多くのお気に入りの選択肢のようです。

+1

+1これを複数回実行するには、CSVはそれを保持するための形式の貧しい選択です。 –

+0

@sendle DBは私の目標です。numpy.loadtxt(file_path、usecols = [1,2,3])が行うことを知っていますか今のところ私は? – dbaron

+0

@dbaron、それはちょうどあなたが "やること"を意味するかどうかにかかっています。私は 'usecols = [1、2、3]'そういう意味で、そうです。私は、ファイル全体を、行単位で、未使用のデータを投げ捨てるように_read_することもかなり確信しています。エッセー、いいえ。 – senderle

関連する問題