41

ファイルから情報を抽出して、対象のレコードのみをフィルタリングし、ジェネレーターが返すタプルに変換するタプル ジェネレーターを作成しました。

以下から DataFrame を作成しようとしました。

import pandas as pd
df = pd.DataFrame.from_records(tuple_generator, columns = tuple_fields_name_list)

しかし、エラーがスローされます:

... 
C:\Anaconda\envs\py33\lib\site-packages\pandas\core\frame.py in from_records(cls, data, index, exclude, columns, coerce_float, nrows)
   1046                 values.append(row)
   1047                 i += 1
-> 1048                 if i >= nrows:
   1049                     break
   1050 

TypeError: unorderable types: int() >= NoneType()

リスト内のジェネレーターを消費して動作するように管理しましたが、2 倍のメモリを使用します。

df = pd.DataFrame.from_records(list(tuple_generator), columns = tuple_fields_name_list)

読み込みたいファイルが大きく、メモリ消費が問題になります。最後の試行では、私のコンピューターは仮想メモリをインクリメントするのに 2 時間を費やしました :(

質問:事前にリストに変換せずに、レコード ジェネレーターから直接 DataFrame を作成する方法を知っている人はいますか?

注: 私は Windows 上の Anaconda で python 3.3 と pandas 0.12 を使用しています。

アップデート:

ファイルの読み取りの問題ではありません。私のタプルジェネレーターはうまく機能します。混合レコードのテキスト圧縮ファイルを1行ずつスキャンし、必要なデータのみを正しいタイプに変換してから、タプルフォームのジェネレーターでフィールドを生成します。数によっては、圧縮されていない約 6.5GB の 130MB の gzip ファイルで 2111412 レコードを、約 1 分でほとんどメモリを使用せずにスキャンします。

Pandas 0.12 ではジェネレーターを使用できません。dev バージョンでは使用できますが、すべてのジェネレーターをリストに入れてからフレームに変換します。効率的ではありませんが、内部でパンダを処理する必要があります。それまでの間、メモリを追加購入することを検討する必要があります。

4

5 に答える 5

20

0.12 バージョンの pandas を使用してジェネレーターから DataFrame を作成することはできません。自分自身を開発バージョンに更新することもできます (github から取得してコンパイルします。これは Windows では少し面倒ですが、私はこのオプションを好みます)。

または、行をフィルタリングしていると言ったので、最初にそれらをフィルタリングし、それらをファイルに書き込んでから、read_csvまたは他の何かを使用してそれらをロードすることができます...

非常に複雑にしたい場合は、行を返すオブジェクトのようなファイルを作成できます。

def gen():
    lines = [
        'col1,col2\n',
        'foo,bar\n',
        'foo,baz\n',
        'bar,baz\n'
    ]
    for line in lines:
        yield line

class Reader(object):
    def __init__(self, g):
        self.g = g
    def read(self, n=0):
        try:
            return next(self.g)
        except StopIteration:
            return ''

そして、次を使用しread_csvます。

>>> pd.read_csv(Reader(gen()))
  col1 col2
0  foo  bar
1  foo  baz
2  bar  baz
于 2013-09-20T12:09:30.263 に答える
7

メモリ効率を高めるには、チャンクで読み取ります。上記の Viktor の Reader クラスを使用して、このようなもの。

df = pd.concat(list(pd.read_csv(Reader(gen()),chunksize=10000)),axis=1)
于 2013-09-20T13:10:09.450 に答える
2

次のようなものを使用することもできます (Python は 2.7.5 でテスト済み)

from itertools import izip

def dataframe_from_row_iterator(row_iterator, colnames):
    col_iterator = izip(*row_iterator)
    return pd.DataFrame({cn: cv for (cn, cv) in izip(colnames, col_iterator)})

これを適応させて、行を DataFrame に追加することもできます。

-- 編集、12 月 4 日: 最後の行に s/row/rows

于 2013-10-29T18:26:58.320 に答える