パンダを使用した「大容量データ」ワークフロー


981

私はパンダを学びながら何ヶ月もの間この質問への答えを困惑させようとしました。私は毎日の仕事にSASを使用しており、コア外のサポートに最適です。しかし、SASは他の多くの理由からソフトウェアの一部としては恐ろしいものです。

ある日、私はSASの使用をpythonとpandasに置き換えたいと思っていますが、現在、大規模なデータセットのコア外のワークフローが不足しています。私は、分散ネットワークを必要とする「ビッグデータ」ではなく、メモリに収まりきらないがハードドライブに収まるには小さすぎるファイルについて話しているのではありません。

私の最初の考えは、を使用HDFStoreしてディスク上に大きなデータセットを保持し、分析のために必要な部分のみをデータフレームにプルすることです。他の人たちは、MongoDBをより使いやすい代替として言及しました。私の質問はこれです:

以下を達成するためのいくつかのベストプラクティスワークフローは何ですか。

  1. フラットファイルを永続的なディスク上のデータベース構造にロードする
  2. データベースをクエリしてデータを取得し、pandasデータ構造にフィードする
  3. パンダのピースを操作した後のデータベースの更新

実世界の例は、特に「大きなデータ」でパンダを使用するすべての人から高く評価されます。

編集-これが機能する方法の例:

  1. 大きなフラットファイルを繰り返しインポートし、永続的なディスク上のデータベース構造に保存します。これらのファイルは通常、大きすぎてメモリに収まりません。
  2. Pandasを使用するために、メモリに収まるこのデータのサブセット(通常は一度に数列のみ)を読みたいと思います。
  3. 選択した列に対してさまざまな操作を実行して、新しい列を作成します。
  4. 次に、これらの新しい列をデータベース構造に追加する必要があります。

これらの手順を実行するためのベストプラクティスの方法を見つけようとしています。パンダとpytablesに関するリンクを読むと、新しい列を追加するのが問題になるようです。

編集-ジェフの質問への具体的な回答:

  1. 私は消費者信用リスクモデルを構築しています。データの種類には、電話、SSN、および住所の特性が含まれます。プロパティ値; 犯罪歴、破産などの軽蔑的な情報...私が毎日使用するデータセットには、混合データタイプの平均で1,000〜2,000のフィールドがあります。数値データと文字データの両方の連続変数、名義変数、順序変数です。行を追加することはめったにありませんが、新しい列を作成する多くの操作を実行します。
  2. 一般的な操作では、条件付きロジックを使用して複数の列を組み合わせて、新しい複合列を作成します。たとえば、if var1 > 2 then newvar = 'A' elif var2 = 4 then newvar = 'B'。これらの操作の結果は、データセット内のすべてのレコードの新しい列です。
  3. 最後に、これらの新しい列をディスク上のデータ構造に追加したいと思います。ステップ2を繰り返して、モデルに対する興味深い直感的な関係を見つけようとするクロス集計と記述統計を使用してデータを探索します。
  4. 通常のプロジェクトファイルは通常約1GBです。ファイルは、行が消費者データのレコードで構成されるような方法で編成されます。各行には、すべてのレコードで同じ数の列があります。これは常に当てはまります。
  5. 新しい列を作成するときに行ごとにサブセットを作成することは非常にまれです。ただし、レポートを作成したり、説明的な統計を生成したりするときに、行をサブセット化することはよくあることです。たとえば、特定の業種の単純なフリークエンシーを作成したい場合があります(小売クレジットカードなど)。これを行うには、レポートする列に加えて、基幹業務=小売のレコードのみを選択します。ただし、新しい列を作成するときは、データのすべての行と、操作に必要な列のみを取得します。
  6. モデリングプロセスでは、すべての列を分析し、結果変数との興味深い関係を探し、それらの関係を記述する新しい複合列を作成する必要があります。私が探索する列は通常、小さなセットで行われます。たとえば、プロパティ値を扱う20列のセットに焦点を当て、それらがローンのデフォルトにどのように関連するかを観察します。それらが探索されて新しい列が作成されたら、次に大学教育などの別の列グループに進み、プロセスを繰り返します。私がやっていることは、私のデータといくつかの結果との関係を説明する候補変数を作成することです。このプロセスの最後に、これらの複合列から方程式を作成するいくつかの学習手法を適用します。

データセットに行を追加することはめったにありません。ほとんどの場合、新しい列(変数または統計/機械学習用語の機能)を作成します。


1
コアサイズ/フルサイズの比率は1%、10%ですか?それは問題ですか?colsをint8に圧縮したり、ノイズのある行を除外したりすると、計算のループが数時間から数分に変わりますか?(タグlarge-dataも追加します。)
denis

1
float64の代わりにfloat32を格納し、可能な場合 int8を格納することは簡単です(ただし、どのツール/関数がfloat64を内部で実行するかはわかりません)
denis

タスクをいくつかの作業に分割できますか?
Andrew Scott Evans

1
メモリに収まらない「中」のデータを操作するようなパンダを実行するための2019年の優れた解決策は暗く
runuini

python + pandasに代わるものがあり、これは、始めたばかりのときに見たいと思うかもしれません。Pythonが汎用のプログラミング言語(データの変更と分析のためのDSLではない)であり、pandasがその上に追加されたライブラリーであるという事実を考慮してください。Rまたはkdbを検討することを検討します。
Henry Henrinson

回答:


621

私はこの方法で数十ギガバイトのデータを日常的に使用しています。たとえば、ディスク上にクエリ経由で読み取るテーブルがあり、データを作成して追加します。

データを保存する方法に関するいくつかの提案については、ドキュメントを読みこのスレッドの後半で読む価値があります。

次のような、データの保存方法に影響を与える詳細:
できるだけ多くの詳細を提供します。そして私はあなたが構造を開発するのを助けることができます。

  1. データのサイズ、行数、列数、列のタイプ。行を追加していますか、それとも列だけですか?
  2. 典型的な操作はどのようになりますか。たとえば、列に対してクエリを実行して一連の行と特定の列を選択し、操作(メモリ内)を実行して新しい列を作成し、これらを保存します。
    (おもちゃの例を挙げれば、より具体的な推奨事項を提供できるようになります。)
  3. その処理の後、あなたは何をしますか?ステップ2は臨時ですか、それとも繰り返し可能ですか?
  4. 入力フラットファイル:Gbでの大まかな合計サイズの数。これらはどのように編成されていますか(例:レコード)。それぞれに異なるフィールドが含まれていますか、または各ファイルのすべてのフィールドを含むファイルごとにいくつかのレコードがありますか?
  5. 基準に基づいて行のサブセット(レコード)を選択したことはありますか(たとえば、フィールドA> 5の行を選択します)。それから何かをするのですか、それともすべてのレコードでフィールドA、B、Cを選択するだけですか(それから何かをします)?
  6. すべての列(グループ)を「処理」しますか、またはレポートにのみ使用できる適切な比率がありますか(たとえば、データを保持したいが、その列を明示的に引き込む必要がない場合)最終結果時間)?

解決

少なくともパンダが0.10.1インストールされていることを確認してください。

ファイルのチャンクごとの反復複数のテーブルクエリを読み取ります

pytablesは行単位(クエリ対象)で動作するように最適化されているため、フィールドのグループごとにテーブルを作成します。このように、小さなフィールドグループを選択するのは簡単です(大きなテーブルで機能しますが、この方法を使用する方が効率的です...将来この制限を修正できるかもしれません...これはとにかくもっと直感的です):(
以下は疑似コードです)

import numpy as np
import pandas as pd

# create a store
store = pd.HDFStore('mystore.h5')

# this is the key to your storage:
#    this maps your fields to a specific group, and defines 
#    what you want to have as data_columns.
#    you might want to create a nice class wrapping this
#    (as you will want to have this map and its inversion)  
group_map = dict(
    A = dict(fields = ['field_1','field_2',.....], dc = ['field_1',....,'field_5']),
    B = dict(fields = ['field_10',......        ], dc = ['field_10']),
    .....
    REPORTING_ONLY = dict(fields = ['field_1000','field_1001',...], dc = []),

)

group_map_inverted = dict()
for g, v in group_map.items():
    group_map_inverted.update(dict([ (f,g) for f in v['fields'] ]))

ファイルを読み込んでストレージを作成する(基本的には何をするかappend_to_multiple):

for f in files:
   # read in the file, additional options may be necessary here
   # the chunksize is not strictly necessary, you may be able to slurp each 
   # file into memory in which case just eliminate this part of the loop 
   # (you can also change chunksize if necessary)
   for chunk in pd.read_table(f, chunksize=50000):
       # we are going to append to each table by group
       # we are not going to create indexes at this time
       # but we *ARE* going to create (some) data_columns

       # figure out the field groupings
       for g, v in group_map.items():
             # create the frame for this group
             frame = chunk.reindex(columns = v['fields'], copy = False)    

             # append it
             store.append(g, frame, index=False, data_columns = v['dc'])

これで、すべてのテーブルがファイルに含まれました(実際には、必要に応じて別々のファイルに保存できます。おそらく、ファイル名をgroup_mapに追加する必要がありますが、おそらくこれは必要ありません)。

これは、列を取得して新しい列を作成する方法です。

frame = store.select(group_that_I_want)
# you can optionally specify:
# columns = a list of the columns IN THAT GROUP (if you wanted to
#     select only say 3 out of the 20 columns in this sub-table)
# and a where clause if you want a subset of the rows

# do calculations on this frame
new_frame = cool_function_on_frame(frame)

# to 'add columns', create a new group (you probably want to
# limit the columns in this new_group to be only NEW ones
# (e.g. so you don't overlap from the other tables)
# add this info to the group_map
store.append(new_group, new_frame.reindex(columns = new_columns_created, copy = False), data_columns = new_columns_created)

post_processingの準備ができたら:

# This may be a bit tricky; and depends what you are actually doing.
# I may need to modify this function to be a bit more general:
report_data = store.select_as_multiple([groups_1,groups_2,.....], where =['field_1>0', 'field_1000=foo'], selector = group_1)

data_columnsについて、あなたは実際に定義する必要はありませんANY data_columnsを。列に基づいて行を副選択できます。例:

store.select(group, where = ['field_1000=foo', 'field_1001>0'])

これらは、最終的なレポート生成段階で最も興味深いかもしれません(基本的に、データ列が他の列から分離されているため、多くを定義すると、効率に多少影響する可能性があります)。

次のこともお勧めします。

  • フィールドのリストを取得する関数を作成し、groups_mapでグループを検索し、それらを選択して結果を連結し、結果のフレームを取得します(これは基本的にselect_as_multipleが行うことです)。このようにして、構造はかなり透過的です。
  • 特定のデータ列のインデックス(行のサブセット化を大幅に高速化)。
  • 圧縮を有効にします。

ご不明な点がありましたらお知らせください。


5
リンクをありがとう。2番目のリンクは、HDFStoreのテーブルに新しい列を追加できないことを少し心配しますか?あれは正しいですか?また、この設定の使用例を追加しました。
Zelazny7 2013年

4
hdfの実際の構造はあなた次第です。Pytablesは行指向であり、作成時に固定列があります。テーブルが作成されると、列を追加できません。ただし、既存のテーブルと同じインデックスが付けられた新しいテーブルを作成できます。(ドキュメントのselect_as_multipleの例を参照してください)。このようにして、かなり効率的なクエリを実行しながら、任意のサイズのオブジェクトを作成できます。データをディスク上でどのように編成するかには、データの使用方法が重要です。より具体的な例の疑似コードを記載したオフリストメールを送ってください。
Jeff

1
細かい点に対応するために質問を更新しました。私はあなたをリストから外すための例に取り組みます。ありがとう!
Zelazny7 2013年

12
@ Jeff、Pandasが0.17.xの場合、上記の問題がPandasで解決されましたか?
ctrl-alt-delete

5
@ジェフは、あなたの答えにクイックアップデートを追加して、夜明けを促進することに熱心ですか?
Boud

137

上記の答えには、私が非常に便利であると思った単純なアプローチが欠けていると思います。

サイズが大きすぎてメモリに読み込めないファイルがある場合、そのファイルを複数の小さなファイル(行または列のいずれか)に分割します

例:30日間の取引データが30GB以下の場合、1日あたり1GB以下のファイルに分割します。その後、各ファイルを個別に処理し、最後に結果を集計します

最大の利点の1つは、ファイル(複数のスレッドまたはプロセスのいずれか)を並列処理できることです。

その他の利点は、ファイル操作(例の日付の追加/削除など)が通常のシェルコマンドで実行できることです。これは、より高度な/複雑なファイル形式では不可能です。

このアプローチはすべてのシナリオをカバーするわけではありませんが、多くのシナリオで非常に役立ちます



83

質問から2年後の今、「コア外」のパンダに相当するdaskがあります。最高です!Pandasのすべての機能をサポートしているわけではありませんが、実際にそれを使用することができます。


6
そしてDASKと完全に働い例えば、ちょうどここを見てstackoverflow.com/questions/37979167/...
ℕʘʘḆḽḘ

データによっては、pystoreを調べることは理にかなっています。頼りdaskです。
gies0r

66

データセットが1〜20 GBの場合、48 GBのRAMを備えたワークステーションを取得する必要があります。その後、パンダはデータセット全体をRAMに保持できます。あなたがここで探している答えはわかりませんが、4GBのRAMを搭載したノートブックで科学計算を行うのは合理的ではありません。


7
「4GBのRAMを搭載したノートブックで科学計算を行うのは合理的ではありません」合理的と定義します。UNIVACは別の見方をすると思います。arstechnica.com/tech-policy/2011/09/...
grisaitis

2
同意しました!たとえ前もって$$がかかるとしても、メモリ内での作業を続けてください。仕事が経済的利益につながる場合は、時間の経過とともに、効率の向上を通じて経費を回収します。
ansonw 2017年

2
48 GBのRAMを搭載したワークステーションで科学計算を行うのは合理的ではありません。
Yaroslav Nikitenko

4
@YaroslavNikitenko 61GB / RAMのr4.2xlargeは$ .532 /時間です。あなたはどのような科学計算を行っていますか?不合理ではないにしても、異常に聞こえます。
rjurney

4
@rjurney申し訳ありませんが、おそらくコメントを削除すべきでした。「理不尽な」科学計算機に対するあなたの判断は非常に主観的なようです。私は何年にもわたってラップトップで科学計算を行っていますが、ほとんどの場合コードを記述しているので、それで十分だと思います。私のアルゴリズムは、計算の観点からよりもプログラミングの観点から見てはるかに困難です。また、スケーラブルなアルゴリズムを作成するために、現在のハードウェアの制限に依存すべきではないと確信しています。他の人のコンピューティングについてのあなたのコメントは(主観性は別として)少し不快に聞こえるかもしれませんが、これらのいくつかの単語を削除してもよろしいですか?
Yaroslav Nikitenko

58

私はこれが古いスレッドであることを知っていますが、Blazeライブラリをチェックする価値があると思います。これらのタイプの状況用に構築されています。

ドキュメントから:

Blazeは、NumPyとPandasの使いやすさを分散型コア外コンピューティングに拡張します。Blazeは、NumPy ND-ArrayまたはPandas DataFrameと同様のインターフェースを提供しますが、これらの使い慣れたインターフェースをPostgresやSparkなどの他のさまざまな計算エンジンにマッピングします。

編集:ちなみに、それはContinuumIOとNumPyの作者であるTravis Oliphantによってサポートされています。


注目に値するもう1つのライブラリはGraphLab Createです。これは、メモリ容量に制限されない、効率的なDataFrameのような構造を持っています。blog.dato.com/...
防水

52

これはpymongoの場合です。また、PythonでSQLサーバー、SQLite、HDF、ORM(SQLAlchemy)を使用してプロトタイプを作成しました。何よりもまずpymongoはドキュメントベースのDBであるため、各人は(dict属性の)ドキュメントになります。多くの人々がコレクションを形成し、あなたは多くのコレクション(人、株式市場、収入)を持つことができます。

pd.dateframe-> pymongo注:私はそれを5〜10kレコードに保つためにchunksizein を使用read_csvしています(pymongoはソケットが大きくなるとドロップします)

aCollection.insert((a[1].to_dict() for a in df.iterrows()))

クエリ:gt =より大きい...

pd.DataFrame(list(mongoCollection.find({'anAttribute':{'$gt':2887000, '$lt':2889000}})))

.find()イテレータを返すので、私は一般的ichunkedに小さなイテレータに切り分けるのに使用します。

通常、10個のデータソースを一緒に貼り付けるので、結合はどうですか?

aJoinDF = pandas.DataFrame(list(mongoCollection.find({'anAttribute':{'$in':Att_Keys}})))

次に(私の場合aJoinDF、「マージ可能」になる前に、最初に我慢しなければならないことがあります。)

df = pandas.merge(df, aJoinDF, on=aKey, how='left')

そして、以下のupdateメソッドを使用して、メインコレクションに新しい情報を書き込むことができます。(論理的収集vs物理的データソース)。

collection.update({primarykey:foo},{key:change})

小さいルックアップでは、単に非正規化します。たとえば、ドキュメントにコードがあり、フィールドコードテキストを追加して、dictドキュメントを作成するときにルックアップを行うだけです。

これで、人を中心とした素晴らしいデータセットができました。各ケースでロジックを解き放ち、より多くの属性を作成できます。最後に、パンダに3からメモリの最大キーインジケーターを読み取り、ピボット/集計/データ探索を行うことができます。これは、数字/大きなテキスト/カテゴリ/コード/浮動小数点数を持つ300万レコードに対して私にとっては機能します...

MongoDBに組み込まれている2つのメソッド(MapReduceおよび集約フレームワーク)を使用することもできます。集約フレームワークの詳細については、こちらをご覧ください。MapReduceよりも簡単で、迅速な集約作業に便利です。フィールドやリレーションを定義する必要がなく、ドキュメントにアイテムを追加できることに注意してください。急速に変化するnumpy、pandas、pythonツールセットの現状では、MongoDBは私が仕事を始めるのに役立ちます:)


こんにちは、私もあなたの例で遊んでいて、データベースに挿入しようとしたときにこのエラーに遭遇しました:In [96]: test.insert((a[1].to_dict() for a in df.iterrows())) --------------- InvalidDocument: Cannot encode object: 0。何が間違っているのでしょうか?私のデータフレームはすべてのint64 dtypeで構成されており、非常に単純です。
Zelazny7 2013年

2
ええ、私は単純な範囲DFについても同じことをしました、そしてnumpyからのint64はpymongoを悩ませているようです。私が試したすべてのデータはCSVからの変換(vs人為的にrange()を介して)であり、型が長く、したがって問題はありません。numpyでは変換できますが、私はそれを邪魔していると思います。HDFがエキサイティングに見えるには10.1アイテムを認めなければなりません。
brian_the_bungler 2013年

43

私はこれを少し遅れて見つけましたが、同様の問題(住宅ローンの前払いモデル)で作業しています。私の解決策は、pandas HDFStoreレイヤーをスキップして、ストレートpytablesを使用することです。各列を個別のHDF5配列として最終的なファイルに保存します。

私の基本的なワークフローは、最初にデータベースからCSVファイルを取得することです。私はそれをgzipで圧縮しているので、それほど大きくありません。次に、Pythonでそれを繰り返し、各行を実際のデータ型に変換し、HDF5ファイルに書き込むことで、行指向のHDF5ファイルに変換します。これには数十分かかりますが、行単位でしか動作しないため、メモリを使用しません。次に、行指向のHDF5ファイルを列指向のHDF5ファイルに「転置」します。

テーブル転置は次のようになります。

def transpose_table(h_in, table_path, h_out, group_name="data", group_path="/"):
    # Get a reference to the input data.
    tb = h_in.getNode(table_path)
    # Create the output group to hold the columns.
    grp = h_out.createGroup(group_path, group_name, filters=tables.Filters(complevel=1))
    for col_name in tb.colnames:
        logger.debug("Processing %s", col_name)
        # Get the data.
        col_data = tb.col(col_name)
        # Create the output array.
        arr = h_out.createCArray(grp,
                                 col_name,
                                 tables.Atom.from_dtype(col_data.dtype),
                                 col_data.shape)
        # Store the data.
        arr[:] = col_data
    h_out.flush()

それを読み返すと、次のようになります。

def read_hdf5(hdf5_path, group_path="/data", columns=None):
    """Read a transposed data set from a HDF5 file."""
    if isinstance(hdf5_path, tables.file.File):
        hf = hdf5_path
    else:
        hf = tables.openFile(hdf5_path)

    grp = hf.getNode(group_path)
    if columns is None:
        data = [(child.name, child[:]) for child in grp]
    else:
        data = [(child.name, child[:]) for child in grp if child.name in columns]

    # Convert any float32 columns to float64 for processing.
    for i in range(len(data)):
        name, vec = data[i]
        if vec.dtype == np.float32:
            data[i] = (name, vec.astype(np.float64))

    if not isinstance(hdf5_path, tables.file.File):
        hf.close()
    return pd.DataFrame.from_items(data)

現在、私はこれを大量のメモリを搭載したマシンで実行しているので、メモリ使用量に十分注意しない場合があります。たとえば、デフォルトでは、ロード操作はデータセット全体を読み取ります。

これは通常私にとってはうまくいきますが、少し不格好であり、ファンシーなpytablesマジックを使用することはできません。

編集:この方法の真の利点は、array-of-recordsのpytablesのデフォルトに比べて、テーブルを処理できないh5rを使用してデータをRにロードできることです。または、少なくとも、異種混合テーブルをロードすることができませんでした。


あなたのコードのいくつかを私と共有してもらえますか?pytablesにプッシュする前に、データ型を知らなくても、フラットテキスト形式からデータをロードする方法に興味があります。また、1つのタイプのデータのみを操作するように見えます。あれは正しいですか?
Zelazny7 2013年

1
まず、データから推測しようとするのではなく、ロードする前に列のタイプを知っていると想定しています。JSONの「データ仕様」ファイルを列名と型で保存し、データを処理するときに使用します。(ファイルは通常、ラベルのないひどいBCP出力です。)私が使用するデータ型は、文字列、浮動小数点数、整数、または月次の日付です。列挙テーブルを保存して文字列をintに変換し、日付をint(2000年を過ぎた月)に変換するので、データにintとfloat、および列挙型だけが残ります。今はフロートをfloat64として保存しますが、float32で実験しました。
Johann Hibschman 2013年

1
時間がある場合、plsはR:pandas.pydata.org/pandas-docs/dev/…との外部互換性を試してみます。問題がある場合は、調整することができます
Jeff

できれば、やってみます。rhdf5は、h5rのようにCRANにあるだけでなく、生体伝導体パッケージであるため、面倒です。私はテクニカルアーキテクチャチームのなすがままになっており、前回リクエストしたところ、rhdf5に問題がありました。いずれにせよ、OLAPストアを列指向ではなく行指向にするのは間違いのようですが、今私はとりとめています。
Johann Hibschman 2013

38

大規模なデータの使用例で役立つと思った1つのトリックは、浮動小数点の精度を32ビットに減らすことによってデータの量を減らすことです。これはすべての場合に適用できるわけではありませんが、多くのアプリケーションでは64ビット精度は過剰であり、2倍のメモリ節約はその価値があります。明白なポイントをさらに明確にするために:

>>> df = pd.DataFrame(np.random.randn(int(1e8), 5))
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000000 entries, 0 to 99999999
Data columns (total 5 columns):
...
dtypes: float64(5)
memory usage: 3.7 GB

>>> df.astype(np.float32).info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000000 entries, 0 to 99999999
Data columns (total 5 columns):
...
dtypes: float32(5)
memory usage: 1.9 GB

26

他の人が指摘しているように、数年後、「コアから外れた」パンダに相当するdaskが現れました。daskはパンダとそのすべての機能の完全な置き換えではありませんが、いくつかの理由で際立っています。

Daskは、パラレルアレイ、データフレーム、およびNumPy、Pandas、Pythonイテレータなどの一般的なインターフェースをより大きなものに拡張する「ビッグデータ」コレクションのインタラクティブな計算ワークロードの動的タスクスケジューリングに最適化された、分析コンピューティング用の柔軟な並列コンピューティングライブラリです。メモリまたは分散環境よりも多く、ラップトップからクラスタまで拡張できます。

Daskは次の美徳を強調しています。

  • 使い慣れた:並列化されたNumPy配列とPandas DataFrameオブジェクトを提供します
  • 柔軟性:より多くのカスタムワークロードと他のプロジェクトとの統合のためのタスクスケジューリングインターフェイスを提供します。
  • ネイティブ:PyDataスタックにアクセスして、Pure Pythonでの分散コンピューティングを可能にします。
  • 高速:オーバーヘッド、待ち時間が少なく、高速数値アルゴリズムに必要な最小限のシリアル化で動作します。
  • スケールアップ:1000コアのクラスターで弾力的に実行します。スケールダウン:ラップトップでセットアップして単一のプロセスで実行するのは簡単です
  • 対応:インタラクティブなコンピューティングを念頭に置いて設計されており、人間を支援するための迅速なフィードバックと診断を提供します

簡単なコードサンプルを追加するには:

import dask.dataframe as dd
df = dd.read_csv('2015-*-*.csv')
df.groupby(df.user_id).value.mean().compute()

このようないくつかのパンダコードを置き換えます:

import pandas as pd
df = pd.read_csv('2015-01-01.csv')
df.groupby(df.user_id).value.mean()

特に注目すべきは、concurrent.futuresカスタムタスクを送信するための一般的なインフラストラクチャをインターフェイスを通じて提供します。

from dask.distributed import Client
client = Client('scheduler:port')

futures = []
for fn in filenames:
    future = client.submit(load, fn)
    futures.append(future)

summary = client.submit(summarize, futures)
summary.result()

@Privateの投稿がコンテンツと長さの削除候補リストに定期的に表示されるため、この回答を追加しました。
wp78de 2017年

17

ここでも言及する価値があります。Rayも、
分散計算フレームワークであり、パンダ用の独自の実装が分散されています。

パンダのインポートを置き換えるだけで、コードはそのまま機能します。

# import pandas as pd
import ray.dataframe as pd

#use pd as usual

ここで詳細を読むことができます:

https://rise.cs.berkeley.edu/blog/pandas-on-ray/


16

もう1つのバリエーション

パンダで行われる操作の多くは、dbクエリ(sql、mongo)として行うこともできます。

RDBMSまたはmongodbを使用すると、DBクエリでいくつかの集計を実行できます(大規模なデータ用に最適化されており、キャッシュとインデックスを効率的に使用します)。

後で、パンダを使用して後処理を実行できます。

この方法の利点は、高レベルの宣言構文でロジックを定義しながら、大きなデータを操作するためのDB最適化を実現できることです。また、メモリで実行することと実行することを決定する詳細を処理する必要がありません。コアの。

クエリ言語とパンダは異なりますが、通常、ロジックの一部を別のロジックに変換することは複雑ではありません。


11

複数の小さなファイルに分割されるデータパイプラインを作成する単純な方法を使用する場合は、Ruffusを検討してください。


9

最近、同様の問題に遭遇しました。チャンクでデータを読み取って、同じcsvにチャンクで書き込むときにデータを追加すると、うまく機能することがわかりました。私の問題は、次のように特定の列の値を使用して、別のテーブルの情報に基づいて日付列を追加することでした。これはdaskとhdf5で混乱しているが、私のようなパンダに慣れている人には役立つかもしれません。

def addDateColumn():
"""Adds time to the daily rainfall data. Reads the csv as chunks of 100k 
   rows at a time and outputs them, appending as needed, to a single csv. 
   Uses the column of the raster names to get the date.
"""
    df = pd.read_csv(pathlist[1]+"CHIRPS_tanz.csv", iterator=True, 
                     chunksize=100000) #read csv file as 100k chunks

    '''Do some stuff'''

    count = 1 #for indexing item in time list 
    for chunk in df: #for each 100k rows
        newtime = [] #empty list to append repeating times for different rows
        toiterate = chunk[chunk.columns[2]] #ID of raster nums to base time
        while count <= toiterate.max():
            for i in toiterate: 
                if i ==count:
                    newtime.append(newyears[count])
            count+=1
        print "Finished", str(chunknum), "chunks"
        chunk["time"] = newtime #create new column in dataframe based on time
        outname = "CHIRPS_tanz_time2.csv"
        #append each output to same csv, using no header
        chunk.to_csv(pathlist[2]+outname, mode='a', header=None, index=None)

8

Vaexパッケージを指摘したいと思います。

Vaexは、大規模な表形式のデータセットを視覚化および探索するための、レイジーなアウトオブコアDataFrames(Pandasに類似)用のPythonライブラリです。1秒あたり10億(10 9)オブジェクト/行までのN次元グリッドで、平均、合計、カウント、標準偏差などの統計を計算できます。可視化は、ヒストグラム、密度プロット、3Dボリュームレンダリングを使用して行われ、ビッグデータのインタラクティブな探索を可能にします。Vaexは、メモリマッピング、ゼロメモリコピーポリシー、および遅延計算を使用して、最高のパフォーマンスを実現します(メモリの浪費はありません)。

ドキュメントをご覧くださいhttps : //vaex.readthedocs.io/en/latest/ APIはパンダのAPIに非常に近いです。


0

なぜパンダなのか?標準Pythonを試しましたか?

標準ライブラリpythonの使用。Pandasは、安定版の最新リリースであっても、頻繁に更新されます。

標準のPythonライブラリを使用すると、コードは常に実行されます。

これを行う1つの方法は、データを保存する方法と、データに関して解決したい質問を把握することです。次に、データを整理する方法(テーブルと考える)のスキーマを描画します。これは、必ずしも正規化ではなく、データのクエリに役立ちます。

あなたはうまく利用することができます:

  • メモリにデータを保存するための辞書のリスト。1つの辞書は1行です。
  • RAMをオーバーフローしないようにデータを行ごとに処理するジェネレーター
  • データをクエリするために理解度をリストし、
  • Counter、DefaultDict、...を利用する
  • 選択した保存ソリューションを使用してハードドライブにデータを保存します。jsonもその1つです。

RamとHDDは時間とともにどんどん安くなっており、標準のpython 3は広く利用可能で安定しています。


-1

現在、私はあなたと同じように、より低い規模で作業しています。そのため、私の提案にPoCがありません。

しかし、私はピクルスをキャッシングシステムとして使用し、さまざまな機能の実行をファイルにアウトソーシングすることに成功しているようです-私のコマンド/メインファイルからこれらのファイルを実行します。たとえば、prepare_use.pyを使用してオブジェクトタイプを変換し、データセットをテスト、検証、予測データセットに分割します。

ピクルスでのキャッシングはどのように機能しますか?渡されたパラメーターとデータセットに応じて、動的に作成されるピクルスファイルにアクセスするために文字列を使用します(データセットに.shape、渡されたdictを使用して、プログラムが既に実行されているかどうかをキャプチャして特定しようとします)パラメーター)。これらの手段を尊重して、.pickleファイルを見つけて読み取ろうとする文字列を取得します。見つかった場合は、現在処理中の実行にジャンプするために処理時間をスキップできます。

データベースを使用して同様の問題が発生したため、このソリューションを使用することに喜びを感じましたが、たとえば、冗長性のために大量のピクルスセットを格納するなど、多くの制約があります。変換前から変換後までのテーブルの更新は、適切なインデックス付けで行うことができます-情報を検証すると、他の本全体が開きます(クロールされた家賃データを統合して、2時間後にデータベースの使用を停止しました-後でジャンプしたかったのですべての変換プロセス)

私の2セントが何らかの形であなたを助けることを願っています。

こんにちは。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.