web-dev-qa-db-ja.com

Pandas DataFrame.merge MemoryError

ゴール

私の目標は、2つのDataFrameを共通の列(遺伝子名)でマージして、各遺伝子行全体の各遺伝子スコアの積を取得できるようにすることです。次に、患者と細胞に対してgroupbyを実行し、それぞれのスコアをすべて合計します。最終的なデータフレームは次のようになります。

    patient  cell 
    Pat_1    22RV1    12
             DU145    15
             LN18      9
    Pat_2    22RV1    12
             DU145    15
             LN18      9
    Pat_3    22RV1    12
             DU145    15
             LN18      9

その最後の部分は正常に機能するはずですが、MemoryErrorのため、遺伝子名の最初のマージを実行できませんでした。以下は、各DataFrameのスニペットです。

データ

cell_s =

    Description          Name                      level_2  0
0  LOC100009676  100009676_at  LN18_CENTRAL_NERVOUS_SYSTEM  1
1  LOC100009676  100009676_at               22RV1_PROSTATE  2
2  LOC100009676  100009676_at               DU145_PROSTATE  3
3          AKT3      10000_at  LN18_CENTRAL_NERVOUS_SYSTEM  4
4          AKT3      10000_at               22RV1_PROSTATE  5
5          AKT3      10000_at               DU145_PROSTATE  6
6          MED6      10001_at  LN18_CENTRAL_NERVOUS_SYSTEM  7
7          MED6      10001_at               22RV1_PROSTATE  8
8          MED6      10001_at               DU145_PROSTATE  9

cell_sは約10,000,000行です

patient_s =

             id level_1  0
0          MED6   Pat_1  1
1          MED6   Pat_2  1
2          MED6   Pat_3  1
3  LOC100009676   Pat_1  2
4  LOC100009676   Pat_2  2
5  LOC100009676   Pat_3  2
6          ABCD   Pat_1  3
7          ABCD   Pat_2  3
8          ABCD   Pat_3  3
    ....

patient_sは約1,200,000行です

コード

def get_score(cell, patient):
    cell_s = cell.set_index(['Description', 'Name']).stack().reset_index()
    cell_s.columns = ['Description', 'Name', 'cell', 's1']

    patient_s = patient.set_index('id').stack().reset_index()
    patient_s.columns = ['id', 'patient', 's2']

    # fails here:
    merged = cell_s.merge(patient_s, left_on='Description', right_on='id')
    merged['score'] = merged.s1 * merged.s2

    scores = merged.groupby(['patient','cell'])['score'].sum()
    return scores

これらのファイルを最初にread_csvするときにMemoryErrorが発生していましたが、dtypesを指定すると問題が解決しました。 pythonは64ビット であることを確認しても、問題は修正されませんでした。パンダの制限に達していませんね。

Python 3.4.3 | Anaconda 2.3.0(64ビット)| Pandas 0.16.2

8
Thomas Matthew

2つの回避策を検討してください。

CSV By CHUNKS

どうやら、 read_csv はパフォーマンスの問題を抱えている可能性があるため、大きなファイルは繰り返しチャンクでロードする必要があります。

cellsfilepath = 'C:\\Path\To\Cells\CSVFile.csv'
tp = pd.io.parsers.read_csv(cellsfilepath, sep=',', iterator=True, chunksize=1000)
cell_s = pd.concat(tp, ignore_index=True)

patientsfilepath = 'C:\\Path\To\Patients\CSVFile.csv'
tp = pd.io.parsers.read_csv(patientsfilepath, sep=',', iterator=True, chunksize=1000)
patient_s = pd.concat(tp, ignore_index=True)

CSV VIA SQL

データベース担当者として、私は常に、大きなデータのロードを処理し、そのようなプロセスに適したSQLリレーショナルエンジンとマージ/結合することをお勧めします。この効果に関するデータフレームマージのQ/Aについて、Rでも多くのコメントを書いています。ファイルサーバーデータベース(Access、SQLite)やクライアントサーバーデータベース(MySQL、MSSQLなど)を含む任意のSQLデータベースを使用できます。あなたのdfsが派生します。 PythonはSQLiteの組み込みライブラリを維持します(それ以外の場合はODBCを使用します)。データフレームは pandas to_sql :を使用してテーブルとしてデータベースにプッシュできます。

import sqlite3

dbfile = 'C:\\Path\To\SQlitedb.sqlite'
cxn = sqlite3.connect(dbfile)
c = cxn.cursor()

cells_s.to_sql(name='cell_s', con = cxn, if_exists='replace')
patient_s.to_sql(name='patient_s', con = cxn, if_exists='replace')

strSQL = 'SELECT * FROM cell_s c INNER JOIN patient_s p ON c.Description = p.id;'
# MIGHT HAVE TO ADJUST ABOVE FOR CELL AND PATIENT PARAMS IN DEFINED FUNCTION

merged = pd.read_sql(strSQL, cxn)
5
Parfait

あなたはそれをバラバラにするか、炎を調べる必要があるかもしれません。 http://blaze.pydata.org

1
Skorpeo