GitHubじゃ!Pythonじゃ!

GitHubからPython関係の優良リポジトリを探したかったのじゃー、でも英語は出来ないから日本語で読むのじゃー、英語社会世知辛いのじゃー

mm-mansour

Fast-Pandas – さまざまなデータフレームサイズに対するパンダのさまざまな操作のベンチマーク

投稿日:

さまざまなデータフレームサイズに対するパンダのさまざまな操作のベンチマーク。

ファスト・パンダ

ベンチマーキングされたパンダチートシート

Pandasは、データ科学者や開発者にとって最も柔軟で強力なツールの1つです。 非常に柔軟性があるため、いくつかの方法で特定のタスクを実行できます。 このプロジェクトは、このような状況で利用可能なさまざまな方法のベンチマークを目指しています。 さらに、numpyとpandasの両方で見つかった関数のための特別なセクションがあります。

前書き:

このプロジェクトは、得られた結果だけを表示するのではなく、異なる操作をベンチマークして結果を共有するための簡単な方法を他の人に提供することを目的としています。

以下は、ベンチマーククラスの使い方の簡単な例です:

from Benchmarker import Benchmarker
import numpy as np
    
def pandas_sum(df):
    return df["A"].sum()
    
def numpy_sum(df):
    return np.sum(df["A"])
    
params = {
    "df_generator": 'pd.DataFrame(np.random.randint(1, df_size, (df_size, 2)), columns=list("AB"))',
    "functions_to_evaluate": [pandas_sum, numpy_sum],
    "title": "Pandas Sum vs Numpy Sum",
}
benchmark = Benchmarker(**params)
benchmark.benchmark_all()
benchmark.print_results()
benchmark.plot_results()

クラスコンストラクタに渡される最初のパラメータはdf_generatorです。これは単純にランダムなデータフレームを生成する関数です。 この関数は、 df_sizeの観点から定義する必要があり、その結果、サイズの増加する異なるデータフレームが生成されます。 2番目のパラメータは評価される関数のリストであり、最後は結果のプロットのタイトルです。

plot_results()を呼び出すと、以下に示すような2つのサブプロットを含むプロットが表示され、保存されます。

  • 最初のサブプロットは、各機能が異なるデータフレームサイズに対して実行された平均時間を示します。 これはセミログプロットであることに注意してください。つまり、y軸はログスケールで表示されます。
  • 第2のサブプロットは、第1の機能に関して他の機能がどのように実行されたかを示す。

100万行以下のデータフレームでは、パンダの合計がnumpyの合計よりもわずかに速いことがはっきり分かります。

結果の要約:

1 – パンダのベンチマーク。

1.1重複行の削除:

パンダに重複した行を削除するための分割方法があります。そのうちの3つは以下のようにテストされています。

def duplicated(df):
    return df[~df["A"].duplicated(keep="first")].reset_index(drop=True)

def drop_duplicates(df):
    return df.drop_duplicates(subset="A", keep="first").reset_index(drop=True)

def group_by_drop(df):
    return df.groupby(df["A"], as_index=False, sort=False).first()
  • 複製は最も速いです。 サイズにかかわらず。
  • group_byドロップは興味深い傾向を示します。 1億行以上のデータフレームでは、複製よりも高速である可能性があります。

1.2 – すべての行を繰り返す:

テストされた機能:

def iterrows_function(df):  
    for index, row in df.iterrows():  
        pass  
 
def itertuples_function(df):  
    for row in df.itertuples():  
        pass
  • itertuplesは、iterrowsよりもはるかに高速です(最大50倍高速)

1.3 – 行の選択:

テストされた機能:

def bracket_selection(df):
    return df[(df["A"] > 0) & (df["A"] < 100)]

def query_selection(df):
    return df.query("A > 0 and A < 100")

def loc_selection(df):
    return df.loc[(df["A"] > 0) & (df["A"] < 100)]

def ne_selection(df):
    A = df["A"].values
    return df[ne.evaluate("(A > 0) & (A < 100)")]

def ne_create_selection(df):
    A = df["A"].values
    mask = ne.evaluate("(A > 0) & (A < 100)")
    return pd.DataFrame(df.values[mask], df.index[mask], df.columns)
  • ne_create_selectionは、10000行よりも小さいデータフレームの中で最速の方法であり、大きなデータフレームの場合はbt ne_selectionが続きます。
  • locとクエリの選択は同じです。
  • 角ブラケットの選択は最も遅い方法です。

1.4 – 新しい列を作成する:

テストされた機能:

def regular(df):
    df["E"] = df["A"] * df["B"] + df["C"]

def eval_method(df):
    df.eval("E = A * B + C", inplace=True)
  • 通常の方法はevalメソッドより高速です。
  • eval_methodsは私が説明できない不規則な挙動を示しています。 しかし、私は数学的操作を変えて数回テストを繰り返し、毎回同じプロットを再現しました。

2 – パンダ対ナンシー。

このセクションでは、numpyとpadnasの両方で検出される関数のパフォーマンスをテストします。

2.1 – 合計パフォーマンス:

テストされた機能:

def pandas_sum(df):
    return df["A"].sum()

def numpy_sum(df):
    return np.sum(df["A"])
  • pandas sumは、100万行以下のデータフレームでは、numpy sumよりもわずかに高速です。

2.2 – ソートのパフォーマンス:

テストされた機能:

def pandas_sort(df):  
  return df["A"].sort_values()  
              
def numpy_sort(df):  
  return np.sort(df["A"])
  • numpy_sortは、サイズに関係なく、パンダよりもかなり高速です。 どちらもクイックソートをデフォルトソートアルゴリズムとして使用します。

2.3 – ユニークなパフォーマンス:

テストされた機能:

def pandas_unique(df):
    return df["A"].unique()

def numpy_unique(df):
    return np.unique(df["A"])
  • 100行以上のデータフレームの場合、pandas uniqueはnumpyより高速です。
  • ユニークなパンダとは異なり、numpy uniqueはソートされた配列を返します。これは結果の不一致を説明しています

2.4 – パフォーマンスの中央値:

テストされた機能:

def pandas_median(df):
    return df["A"].median()

def numpy_median(df):
    return np.median(df["A"])
  • パフォーマンスに有意な統計的差はない。

2.5 – 平均パフォーマンス:

テストされた機能:

def pandas_mean(df):
    return df["A"].mean()

def numpy_mean(df):
    return np.mean(df["A"])
  • pandas平均は、100万行以下のデータフレームでは、numpy平均よりやや速いです。

2.6 – 製品の性能:

テストされた機能:

def pandas_prod(df):
    return df["A"].prod()

def numpy_prod(df):
    return np.prod(df["A"])
  • pandas製品は、100万行以下のデータフレームでは、numpy製品よりもわずかに高速です。

追加メモ:

余分なパラメータ:

クラスコンストラクタには、3つのオプションのパラメータがあります。

"user_df_size_powers": List[int] containing the log10(sizes) of the test_dfs
"user_loop_size_powers": List[int] containing the log10(sizes) of the loops_sizes
"largest_df_single_test" (defualt = True)

ベンチマークで使用するデータフレームとループのカスタムサイズを渡すことができます。これは、結果にノイズがあると思われる場合に推奨されます。 つまり、異なる実行で一貫性を維持することはできません。 3番目のパラメータ、 largest_df_single_testは、 デフォルトではtrueに設定されています。 最後のデータフレームには1億の行があり、一部の操作では1つのタスクを完了するのに多くの時間がかかります。

警告:

評価された関数によって返された結果が同一でない場合、ベンチマーク担当者が警告します。 上記のnp.unique関数のベンチマークで示されているように、心配する必要はありません。

今後の課題:

– ノイズの発生が少ないため平均値の代わりに中央値を使用します。

-Benchmarkingメモリ消費。


あなたがベンチマークしたいと思う何かを得ましたか? 私たちはあなたの結果を待っています。







-mm-mansour

執筆者: