pandas:計算時にメモリが不足したらどうする(evalとquery)


pandas:計算時にメモリが不足したらどうする(evalとquery)
  • 前言
  • 一、eval()とquery()の由来
  • 二、eval()の紹介
  • 1.pandas.DataFrame.eval
  • 2.pandas.eval

  • 三、query()の紹介
  • まとめ
  • 前言
    前のいくつかの文章では、pandas計算を大幅に向上させる方法を紹介しました.その中には、pandas高速処理文字列法とmap、apply、applymap関数を使用してデータを一括処理し、通常のサイクル操作処理データより500倍以上速く処理する方法が含まれています.本稿では、pandas計算のメモリ節約と加速についてお話しします.
    ヒント:問題を簡単かつ迅速に解決するために、本文は関数の主な使い方だけを紹介し、全面的に紹介するわけではない.
    一、eval()とquery()の由来
    numpyとpandasはいずれもPythonが強力な生態の基礎ライブラリを構築しており、彼らの強みは内蔵の方法で基本操作をC言語に変換することであり、numpyの中には量子化と放送演算があり、pandasはパケット型演算である.便利で迅速な同時にもたらす問題は、一時的な中間オブジェクトを構築する必要があることであり、計算メモリと時間を大量に消費し、pandasのeval()とquery()はこの問題を解決するために発生し、eval()関数はpandasにも分けられる.エヴァ()とpandas.DataFrame.eval():pandas.eval()は、複数のデータFrame間の計算に使用することができる、pandas.DataFrame.eval()は、DataFrameのカラム間の計算にのみ使用されます.
    二、eval()の紹介
    1.pandas.DataFrame.eval
    DataFrame.eval(expr, inplace=False, **kwargs)
    パラメータ:expr:str;計算する式文字列.inplace:bool、デフォルトFalse;元のDataFrameを上書きするか、新しいDataFrameを出力するかを設定します.**kwargs:pandasを入力できます.eval()の変数は、後で詳しく説明します.
    ndarray、scalar、またはpandasデータ型を返します.
    次に例を示します.まずDataFrameを作成します.
    import pandas as pd
    import numpy as np
    import time
    
    data = pd.DataFrame(np.random.rand(10000,2),columns=['A','B'])
    data.head()
    
              A         B
    0  0.161016  0.166286
    1  0.859612  0.221388
    2  0.814103  0.984277
    3  0.776477  0.302750
    4  0.996164  0.760127
    

    A、B列の合計を通常の方法で計算し、時間を消費します.
    start = time.time()
    result = data['A'] + data['B']
    end = time.time()
    print(str(end-start))
    
    0.9478774070739746
    

    DataFrameを使用します.eval()メソッド計算および計算にかかる時間
    start = time.time()
    result = data.eval('A+B')
    end = time.time()
    print(str(end-start))
    
    0.1408524513244629
    

    直接列相より6.7倍速くなったことがわかる.
    ヒント:コンピュータ環境によって計算速度の差も異なり,筆者の実験は参考にした.
    DataFrame.eval()は、計算結果を新しい列に追加することもできます.
    data.eval('C = A+B',inplace=True)
    data.head()
    
              A         B         C
    0  0.161016  0.166286  0.327302
    1  0.859612  0.221388  1.081000
    2  0.814103  0.984277  1.798380
    3  0.776477  0.302750  1.079227
    4  0.996164  0.760127  1.756291
    

    @メソッドを使用してローカル変数を計算に使用できます.
    test_num = 100
    result = data.eval('A + B + @test_num')
    result.head()
    
    0    100.327302
    1    101.081000
    2    101.798380
    3    101.079227
    4    101.756291
    dtype: float64
    

    2.pandas.eval
    pandas.evalは、複数のDataFrameまたはSeriesで計算することができます.
    pandas.eval(expr, parser=‘pandas’, engine=None, truediv=, local_dict=None, global_dict=None, resolvers=(), level=0, target=None, inplace=False)
    主なパラメータ:ヒント:パラメータが多すぎて、私が主だと思ってよく使ういくつかのパラメータだけを紹介して、もし全面的に理解する必要があるならば公式の紹介を参照してください
    expr:str;計算する式は、この文字列にPython式しか含まれません.
    parser:{‘pandas’,‘python’},デフォルト‘pandas’;pandas構文かPython構文解析式かを選択し、ここでデフォルトにすればいいです.
    target:object,optional,デフォルトNone;処理するターゲットを選択します.
    inplace:bool、デフォルトFalse;targetで指定したオブジェクトを置き換えるかどうかを選択します.
    次に例を示します.DataFrameの場合
    import pandas as pd
    import numpy as np
    import time
    
    data = pd.DataFrame(np.random.rand(10000,2),columns=['A','B'])
    result = pd.eval('data.A+data.B')
    result.head()
    
    0    1.265516
    1    1.191837
    2    1.443026
    3    0.595921
    4    1.442945
    dtype: float64
    

    異なるDataFrameについて(公式ケース参照)
    nrows, ncols = 20000, 100
    df1, df2, df3, df4 = [pd.DataFrame(np.random.randn(nrows, ncols)) for _ in range(4)]
    add_pd = pd.eval('df1 + df2 + df3 + df4')
    add_pd.head()
    
             0         1         2     ...           97        98        99
    0 -0.484481 -1.593759 -0.540393    ...    -0.688837 -1.212668  2.375383
    1  2.846088 -0.053718  2.861517    ...    -0.514399 -0.520711  1.378200
    2  1.034824 -1.387115 -1.056278    ...     0.017538 -0.339709  1.773171
    3 -4.820074  3.141094 -0.829376    ...    -0.494888 -1.280396 -0.803026
    4  0.950161  0.253045 -0.977115    ...     3.878627  3.171613 -0.349569
    
    [5 rows x 100 columns]
    

    三、query()の紹介
    pandas.DataFrame.Query()の役割は、DataFrameのクエリーをメモリを節約することであり、実際に使用すると速度は通常の方法では速くありません.
    DataFrame.query(expr, inplace=False, **kwargs)
    パラメータ:expr:str;計算する式.
    inplace:bool;データを変更するか、変更したコピーデータを返すかを選択します.
    次に例と比較例を示します
    import pandas as pd
    import numpy as np
    import time
    
    data = pd.DataFrame(np.random.rand(10000,2),columns=['A','B'])
    data.head()
    
              A         B
    0  0.941237  0.568980
    1  0.191276  0.083936
    2  0.612065  0.662790
    3  0.985512  0.446884
    4  0.033947  0.610931
    

    A列とB列ともに0.5未満のデータをフィルタ
    result = data.query('A < 0.5 and B < 0.5')
    result.head()
    
               A         B
    1   0.191276  0.083936
    9   0.395155  0.495593
    19  0.284068  0.399290
    24  0.334158  0.301924
    25  0.297931  0.326648
    

    同様に@メソッドでローカル変数を呼び出すこともできます
    num = 0.5
    result = data.query('A < @num and B < @num')
    result.head()
    
               A         B
    1   0.191276  0.083936
    9   0.395155  0.495593
    19  0.284068  0.399290
    24  0.334158  0.301924
    25  0.297931  0.326648
    

    まとめ
    pandasを使用して大量のデータを計算すると、メモリが不足し、時間がかかりすぎるという問題が発生するのは避けられません.evalとqueryメソッドを使用すると、このような問題を簡単に解決できますが、データ量が少ない場合はこの方法を使用しても効果はありません.引き続き筆者はデータ科学に関する方法と技術を共有し続けますので、ご注目ください∩.