Pandasは本当に素晴らしいですが、Pandas.DataFrameから値を取得するのがどれほど効率的でないかに本当に驚いています。次のおもちゃの例では、DataFrame.ilocメソッドでさえ、辞書よりも100倍以上遅いです。
質問:ここでの教訓は、辞書が価値を調べるためのより良い方法であるということですか?はい、私はそれがまさに彼らが作られたものだと思います。しかし、DataFrameのルックアップパフォーマンスに関して何か足りないものがあるのではないかと思っています。
この質問は「尋ねる」よりも「気になる」ことを理解していますが、これについての洞察や視点を提供する答えを受け入れます。ありがとう。
import timeit
setup = '''
import numpy, pandas
df = pandas.DataFrame(numpy.zeros(shape=[10, 10]))
dictionary = df.to_dict()
'''
f = ['value = dictionary[5][5]', 'value = df.loc[5, 5]', 'value = df.iloc[5, 5]']
for func in f:
print func
print min(timeit.Timer(func, setup).repeat(3, 100000))
値=辞書[5] [5]
0.130625009537
値= df.loc [5、5]
19.4681699276
値= df.iloc [5、5]
17.2575249672
ディクテーションはDataFrameに対するもので、自転車は車に対するものです。車を始動したり、ギアを入れたりするよりも速く自転車で10フィートのペダルを踏むことができます。
特定の小規模なターゲットを絞った目的では、辞書の方が高速になる場合があります。そして、それがあなたが必要とするすべてであるなら、確かに辞書を使ってください!しかし、DataFrameのパワーと豪華さを必要とする場合は、辞書に代わるものではありません。データ構造が最初にニーズを満たさない場合、速度を比較することは無意味です。
たとえば、より具体的に言えば、dictは列へのアクセスには適していますが、行へのアクセスにはそれほど便利ではありません。
import timeit
setup = '''
import numpy, pandas
df = pandas.DataFrame(numpy.zeros(shape=[10, 1000]))
dictionary = df.to_dict()
'''
# f = ['value = dictionary[5][5]', 'value = df.loc[5, 5]', 'value = df.iloc[5, 5]']
f = ['value = [val[5] for col,val in dictionary.items()]', 'value = df.loc[5]', 'value = df.iloc[5]']
for func in f:
print(func)
print(min(timeit.Timer(func, setup).repeat(3, 100000)))
利回り
value = [val[5] for col,val in dictionary.iteritems()]
25.5416321754
value = df.loc[5]
5.68071913719
value = df.iloc[5]
4.56006002426
そのため、リストの辞書は、df.iloc
。カラムの数が増えると、速度不足が大きくなります。 (列の数は、自転車の例えでの足の数に似ています。距離が長いほど、車は便利になります...)
これは、リストの辞書がDataFrameよりも便利/遅い場合のほんの一例です。
別の例は、行のDatetimeIndexがあり、特定の日付の間のすべての行を選択したい場合です。 DataFrameでは、次を使用できます
df.loc['2000-1-1':'2000-3-31']
リストの辞書を使用する場合、そのための簡単な類似物はありません。また、正しい行を選択するために使用する必要があるPythonループは、DataFrameに比べて非常に遅くなります。
パフォーマンスの差は今ではずっと小さくなっているようです(0.21.1-元の例ではPandasのバージョンを忘れていました)。辞書アクセスと.loc
減少(約335倍から126倍遅く)、loc
(iloc
)はat
(iat
)よりも2倍遅い。
In [1]: import numpy, pandas
...: ...: df = pandas.DataFrame(numpy.zeros(shape=[10, 10]))
...: ...: dictionary = df.to_dict()
...:
In [2]: %timeit value = dictionary[5][5]
85.5 ns ± 0.336 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [3]: %timeit value = df.loc[5, 5]
10.8 µs ± 137 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [4]: %timeit value = df.at[5, 5]
6.87 µs ± 64.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [5]: %timeit value = df.iloc[5, 5]
14.9 µs ± 114 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [6]: %timeit value = df.iat[5, 5]
9.89 µs ± 54.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [7]: print(pandas.__version__)
0.21.1
----以下の元の回答----
at
またはスカラー演算にiat
を使用する場合は+1。ベンチマークの例:
In [1]: import numpy, pandas
...: df = pandas.DataFrame(numpy.zeros(shape=[10, 10]))
...: dictionary = df.to_dict()
In [2]: %timeit value = dictionary[5][5]
The slowest run took 34.06 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 310 ns per loop
In [4]: %timeit value = df.loc[5, 5]
10000 loops, best of 3: 104 µs per loop
In [5]: %timeit value = df.at[5, 5]
The slowest run took 6.59 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 9.26 µs per loop
In [6]: %timeit value = df.iloc[5, 5]
10000 loops, best of 3: 98.8 µs per loop
In [7]: %timeit value = df.iat[5, 5]
The slowest run took 6.67 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 9.58 µs per loop
at
(iat
)を使用すると、loc
(iloc
)よりも約10倍高速になるようです。
同じ問題が発生しました。 at
を使用して改善できます。
「[]を使用したインデックス作成は多くの場合(単一ラベルアクセス、スライス、ブール型インデックス作成など)を処理する必要があるため、要求内容を把握するために多少のオーバーヘッドがあります。スカラー値にアクセスする場合、最速の方法は、すべてのデータ構造に実装されているat
およびiat
メソッドを使用することです。
公式リファレンスを参照してください http://pandas.pydata.org/pandas-docs/stable/indexing.html 「高速スカラー値の取得と設定」の章
セルにアクセスする最も速い方法は
df.get_value(row,column)
df.set_value(row,column,value)
どちらも(私は思う)よりも高速です
df.iat(...)
df.at(...)
データフレーム行へのアクセスについて、さまざまな現象が発生しました。この単純な例を約10,000,000行のデータフレームでテストします。辞書が揺れる。
def testRow(go):
go_dict = go.to_dict()
times = 100000
ot= time.time()
for i in range(times):
go.iloc[100,:]
nt = time.time()
print('for iloc {}'.format(nt-ot))
ot= time.time()
for i in range(times):
go.loc[100,2]
nt = time.time()
print('for loc {}'.format(nt-ot))
ot= time.time()
for i in range(times):
[val[100] for col,val in go_dict.iteritems()]
nt = time.time()
print('for dict {}'.format(nt-ot))