[Python3] Pandas v1.0-(九)高性能Pandas:eval()とquery()
文書ディレクトリ 十二、高性能Pandas:eval()とquery() (一)query()とeval()の設計動機:複合代数式 (二)用pandas.eval()高性能演算 を実現 pd.eval()がサポートする演算 (1)算術演算子 (2)比較演算子 (3)ビット演算子 (4)オブジェクト属性とインデックス (5)その他の演算
(三)用DataFrame.eval()実装カラム間演算 1. DataFrameでeval()新規列 2. DataFrame.eval()ローカル変数 を使用
(四)DataFrame.query()メソッド (五)性能決定使用タイミング
[ Pandas version: 1.0.1 ]
十二、高性能Pandas:eval()とquery()
Pandasデータ科学生態環境の強大な力はNumPyとPandasの基礎の上で創立して、そして直観的な文法を通じて基本操作をC言語に変換します:NumPyの中で量子化/放送演算で、Pandasの中でグループ型の演算です.
これらの抽象機能は、多くの問題を簡潔かつ効率的に解決できますが、一時的な中間オブジェクトを作成する必要があることがよくあります.これにより、計算時間とメモリが大幅に消費されます.
Pandasは0.13版から実験的なツールを導入し,ユーザがC言語速度の操作を直接実行できるようにし,中間配列の構成に苦労する必要がない.これらは
(一)query()とeval()の設計動機:複合代数式
NumPyとPandasの高速量子化演算は、通常のPythonサイクルやリストの統合よりもずっと速い.
しかし、この演算は複合代数式(compound expression)の問題を処理する際に効率が低く、各セグメントの中間プロセスにメモリを明示的に割り当てる必要がある.
x配列とy配列が非常に大きい場合、演算には多くの時間とメモリ消費がかかります.
Numexprパッケージは、中間プロセスにすべてのメモリを割り当てない前提で、要素から要素への複合代数演算(NumPyスタイルの文字列代数式で演算)を完了することができます.の利点:Numexprは代数式を計算する際に一時配列にすべてのメモリを割り当てる必要がないため、計算はNumPyよりも効率的であり、特に大型配列 の処理に適している. Pandasの である.
(二)pandas.eval()高性能演算を実現
Pandasの pandas.eval() - pandas 1.0.1 documentation
pd.eval()がサポートする演算
(1)算術演算子
(2)比較演算子
(3)ビット演算子
(4)オブジェクト属性とインデックス
(5)その他の演算
(三)DataFrameを用いる.eval()実装カラム間演算変数としてカラム名を用いる代数式を計算することも同様に可能である . pandas.DataFrame.eval - pandas 1.0.1 documentation
1.DataFrame.eval()新規列
2. DataFrame.eval()ローカル変数の使用 を計算する.注意: しか取得できないためです.
(四)DataFrame.query()メソッド
DataFrameは文字列代数式の演算に基づいて を参照することをサポートする.
(五)性能決定使用タイミング
この2つの関数を使用するかどうかを考えるには、計算時間とメモリ消費、メモリ消費がより重要な影響要因であるという2つの側面を考える必要があります. NumPy配列またはPandasに関するDataFrameの各複合代数式は、一時配列 を生成する.一時データFrameのメモリ要件がシステムメモリよりも大きい場合は、 を使用することが望ましい.
性能面では、最大のシステムメモリが使用されていなくても、現在のパフォーマンスのボトルネックは、一時的なDataFrameとシステムCPUのL 1およびL 2キャッシュとの比較となり、システムキャッシュが十分に大きい場合、 をゆっくり移動することを回避することができる.実際の作業では、一般的な計算方法と よりも速い.
Pandas関連読書:
[Python3] Pandas v1.0-(一)オブジェクト、データ値と演算[python 3]Pandas v 1.0-(二)欠落値の処理[Python 3]Pandas v 1.0-(3)階層インデックス[python 3]Pandas v 1.0-(四)データセットのマージ[python 3]Pandas v 1.0-(五)累計とパケット[Python 3]Pandas v 1.0-(六)データピボットテーブル[python 3]Pandas v 1.0-(7)量子化文字列操作[python 3]Pandas v 1.0-(8)処理時系列[python 3]Pandas v 1.0——(九)高性能Pandas:eval()とquery()【本文】
『Pythonデータ科学マニュアル』よりまとめ
[ Pandas version: 1.0.1 ]
十二、高性能Pandas:eval()とquery()
Pandasデータ科学生態環境の強大な力はNumPyとPandasの基礎の上で創立して、そして直観的な文法を通じて基本操作をC言語に変換します:NumPyの中で量子化/放送演算で、Pandasの中でグループ型の演算です.
これらの抽象機能は、多くの問題を簡潔かつ効率的に解決できますが、一時的な中間オブジェクトを作成する必要があることがよくあります.これにより、計算時間とメモリが大幅に消費されます.
Pandasは0.13版から実験的なツールを導入し,ユーザがC言語速度の操作を直接実行できるようにし,中間配列の構成に苦労する必要がない.これらは
eval()
およびquery()
の関数であり、いずれもNumexprパッケージに依存する.(一)query()とeval()の設計動機:複合代数式
NumPyとPandasの高速量子化演算は、通常のPythonサイクルやリストの統合よりもずっと速い.
#
import numpy as np
rng = np.random.RandomState(42)
x = rng.rand(int(1E6))
y = rng.rand(int(1E6))
%timeit x + y
# 3.54 ms ± 172 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit np.fromiter((xi + yi for xi, yi in zip(x, y)), dtype=x.dtype, count=len(x))
# 470 ms ± 29.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
しかし、この演算は複合代数式(compound expression)の問題を処理する際に効率が低く、各セグメントの中間プロセスにメモリを明示的に割り当てる必要がある.
x配列とy配列が非常に大きい場合、演算には多くの時間とメモリ消費がかかります.
mask = (x > 0.5) & (y < 0.5)
# NumPy , :
# tmp1 = (x > 0.5)
# tmp2 = (y < 0.5)
# mask = tmp1 & tmp2
Numexprパッケージは、中間プロセスにすべてのメモリを割り当てない前提で、要素から要素への複合代数演算(NumPyスタイルの文字列代数式で演算)を完了することができます.
eval()
およびquery()
ツールもNumexprに基づくimport numexpr
mask_numexpr = numexpr.evaluate('(x > 0.5) & (y < 0.5)')
np.allclose(mask, mask_numexpr)
# True
(二)pandas.eval()高性能演算を実現
Pandasの
eval()
関数は文字列代数式でDataFrameの高性能演算を実現した.import pandas as pd
nrows, ncols = 100000, 100
rng = np.random.RandomState(42)
df1, df2, df3, df4 = (pd.DataFrame(rng.rand(nrows, ncols)) for i in range(4))
# Pandas DataFrame
%timeit df1 + df2 + df3 + df4
# 93.4 ms ± 8.72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# pd.eval ( , )
%timeit pd.eval('df1 + df2 + df3 + df4')
# 49.4 ms ± 3.82 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
np.allclose(df1 + df2 + df3 + df4, pd.eval('df1 + df2 + df3 + df4'))
# True
pd.eval()がサポートする演算
# DataFrame
df1, df2, df3, df4, df5 = (pd.DataFrame(rng.randint(0, 100, (100, 3))) for i in range(5))
(1)算術演算子
pd.eval()
はすべての演算子をサポートしますresult1 = -df1 * df2 / (df3 + df4) - df5
result2 = pd.eval('-df1 * df2 / (df3 + df4) - df5')
np.allclose(result1, result2)
# True
(2)比較演算子
pd.eval()
は、チェーン代数式(chained expression)を含むすべての比較演算子+, -, *, /, **, %, //
をサポートする.result1 = (df1 < df2) & (df2 <= df3) & (df3 != df4)
result2 = pd.eval('df1 < df2 <= df3 != df4')
np.allclose(result1, result2)
# True
(3)ビット演算子
pd.eval()
は| (or), & (and), ~ (not)
等位演算子をサポートし、またブール型の代数式でand
とor
等の文字面値を使用することもできる.result1 = (df1 < 0.5) & (df2 < 0.5) | (df3 < df4)
result2 = pd.eval('(df1 < 0.5) & (df2 < 0.5) | (df3 < df4)')
np.allclose(result1, result2)
# True
result3 = pd.eval('(df1 < 0.5) and (df2 < 0.5) or (df3 < df4)')
np.allclose(result1, result3)
# True
(4)オブジェクト属性とインデックス
pd.eval()
は、obj.attr
構文によってオブジェクト属性を取得し、obj[index]
構文によってオブジェクトインデックスを取得することができるresult1 = df2.T[0] + df3.iloc[1]
result2 = pd.eval('df2.T[0] + df3.iloc[1]')
np.allclose(result1, result2)
# True
(5)その他の演算
pd.eval()
は、関数呼び出し、条件文、ループ、およびより複雑な演算を一時的にサポートしません(ただし、Numexprによって実装できます).(三)DataFrameを用いる.eval()実装カラム間演算
pd.eval()
はPandasの最上位関数であるため、DataFrameにはeval()
の方法で同様の演算が可能である.eval()
メソッドを使用する利点は、カラム名を使用して演算できることです.df = pd.DataFrame(rng.rand(1000, 3), columns=['A', 'B', 'C'])
df.head()
# A B C
# 0 0.374540 0.950714 0.731994
# 1 0.598658 0.156019 0.155995
# 2 0.058084 0.866176 0.601115
# 3 0.708073 0.020584 0.969910
# 4 0.832443 0.212339 0.181825
# od.eval()
result1 = (df['A'] + df['B']) / (df['C'] - 1)
result2 = pd.eval('(df.A + df.B) / (df.C - 1)')
np.allclose(result1, result2)
# True
# DataFrame.eval()
result3 = df.eval('(A + B) / (C - 1)')
np.allclose(result1, result3)
# True
1.DataFrame.eval()新規列
DataFrame.eval()
はまた、新しいカラムを作成することもできます.df.head()
# A B C
# 0 0.374540 0.950714 0.731994
# 1 0.598658 0.156019 0.155995
# 2 0.058084 0.866176 0.601115
# 3 0.708073 0.020584 0.969910
# 4 0.832443 0.212339 0.181825
# df.eval() 'D'
df.eval('D = (A + B) / C', inplace=True)
df.head()
# A B C D
# 0 0.374540 0.950714 0.731994 1.810472
# 1 0.598658 0.156019 0.155995 4.837844
# 2 0.058084 0.866176 0.601115 1.537576
# 3 0.708073 0.020584 0.969910 0.751263
# 4 0.832443 0.212339 0.181825 5.746085
#
df.eval('D = (A - B) / C', inplace=True)
df.head()
# A B C D
# 0 0.374540 0.950714 0.731994 -0.787130
# 1 0.598658 0.156019 0.155995 2.837535
# 2 0.058084 0.866176 0.601115 -1.344323
# 3 0.708073 0.020584 0.969910 0.708816
# 4 0.832443 0.212339 0.181825 3.410442
2. DataFrame.eval()ローカル変数の使用
DataFrame.eval()
メソッドはまた、@
シンボルを介してPythonを使用するローカル変数をサポートする.@
符号は「1つのカラム名ではなく変数名」を表し、2つの「ネーミングスペース」のリソース(カラム名のネーミングスペースとPythonオブジェクトのネーミングスペース)を活用して代数式@
記号はDataFrame.eval()
メソッドでのみ使用でき、pd.eval()
関数では使用できません.pd.eval()
関数はPythonネーミングスペースの1つのコンテンツcolumn_mean = df.mean(1)
result1 = df['A'] + column_mean
result2 = df.eval('A + @column_mean')
np.allclose(result1, result2)
# True
(四)DataFrame.query()メソッド
DataFrameは文字列代数式の演算に基づいて
query()
と呼ばれる別の方法を実現した.query()
の方法はまた、@
符号で局所変数result1 = df[(df.A < 0.5) & (df.B < 0.5)]
result2 = pd.eval('df[(df.A < 0.5) & (df.B < 0.5)]')
np.allclose(result1, result2)
# True
# DataFrame , `DataFrame.eval()`
# query()
result2 = df.query('A < 0.5 and B < 0.5')
np.allclose(result1, result2)
# True
Cmean = df['C'].mean()
result1 = df[(df.A < Cmean) & (df.B < Cmean)]
result2 = df.query('A < @Cmean and B < @Cmean')
np.allclose(result1, result2)
# True
(五)性能決定使用タイミング
この2つの関数を使用するかどうかを考えるには、計算時間とメモリ消費、メモリ消費がより重要な影響要因であるという2つの側面を考える必要があります.
x = df[(df.A < 0.5) & (df.B < 0.5)]
# :
# tmp1 = df.A < 0.5
# tmp2 = df.B < 0.5
# tmp3 = tmp1 & tmp2
# x = df[tmp3]
eval()
とquery()
の代数式# :
df.values.nbytes
# 32000
性能面では、最大のシステムメモリが使用されていなくても、
eval()
の計算速度は通常の方法よりも速い.eval()
は、異なるキャッシュ間で一時ファイルeval/query
の計算方法の計算時間の違いは、常にそれほど顕著ではなく、一般的な方法は、より小さな配列を処理する際に、かえってeval/query
メソッドの利点は、主にメモリを節約することであり、構文もより簡潔になることがあります.Pandas関連読書:
[Python3] Pandas v1.0-(一)オブジェクト、データ値と演算[python 3]Pandas v 1.0-(二)欠落値の処理[Python 3]Pandas v 1.0-(3)階層インデックス[python 3]Pandas v 1.0-(四)データセットのマージ[python 3]Pandas v 1.0-(五)累計とパケット[Python 3]Pandas v 1.0-(六)データピボットテーブル[python 3]Pandas v 1.0-(7)量子化文字列操作[python 3]Pandas v 1.0-(8)処理時系列[python 3]Pandas v 1.0——(九)高性能Pandas:eval()とquery()【本文】
『Pythonデータ科学マニュアル』よりまとめ