特定の状況で動作が異なる可能性のある実装の詳細を測定していることが多いため、Pythonで特定のやり方で「すべきである」ということはあまり重大ではありません。その結果、人々は何がより速くすべきかを推測するとき、しばしば(通常?)間違っています。たとえば、私はmap
が実際には遅くなることがわかります。このセットアップコードを使用する:
import numpy as np, pandas as pd
import random, string
def make_test(num, width):
s = [''.join(random.sample(string.ascii_lowercase, width)) for i in range(num)]
df = pd.DataFrame({"a": s})
return df
はのは、彼らがインデックスオブジェクトを作成するのにかかる時間を比較してみましょう - かどうか
Series
または
list
- そしてそれは
DataFrame
へのインデックスにそのオブジェクトを使用するのにかかる結果の時間。たとえば、リストを作成するのは高速ですが、インデックスとして使用する前に、内部で
Series
または
ndarray
などに変換する必要があります。余分な時間が追加されます。
まず、小さなフレーム用:
>>> df = make_test(10, 10)
>>> %timeit df['a'].map(lambda x: x.startswith('t'))
10000 loops, best of 3: 85.8 µs per loop
>>> %timeit [x.startswith('t') for x in df['a']]
100000 loops, best of 3: 15.6 µs per loop
>>> %timeit df['a'].str.startswith("t")
10000 loops, best of 3: 118 µs per loop
>>> %timeit df[df['a'].map(lambda x: x.startswith('t'))]
1000 loops, best of 3: 304 µs per loop
>>> %timeit df[[x.startswith('t') for x in df['a']]]
10000 loops, best of 3: 194 µs per loop
>>> %timeit df[df['a'].str.startswith("t")]
1000 loops, best of 3: 348 µs per loop
とlistcompが最速である。この場合、
。
lambda
を経由すると直接
str.startswith
を使用するよりも遅くなる可能性が高いので、実際にはあまりにも私をあまりにも驚かせるわけではありませんが、推測するのは本当に難しいです。 10が十分小さいので、おそらくまだ
Series
の設定コストのようなものを測定しています。大きなフレームではどうなりますか?
>>> df = make_test(10**5, 10)
>>> %timeit df['a'].map(lambda x: x.startswith('t'))
10 loops, best of 3: 46.6 ms per loop
>>> %timeit [x.startswith('t') for x in df['a']]
10 loops, best of 3: 27.8 ms per loop
>>> %timeit df['a'].str.startswith("t")
10 loops, best of 3: 48.5 ms per loop
>>> %timeit df[df['a'].map(lambda x: x.startswith('t'))]
10 loops, best of 3: 47.1 ms per loop
>>> %timeit df[[x.startswith('t') for x in df['a']]]
10 loops, best of 3: 52.8 ms per loop
>>> %timeit df[df['a'].str.startswith("t")]
10 loops, best of 3: 49.6 ms per loop
、インデックスとして使用した場合map
が勝っているように差が限界ですが、今では、と思われます。しかしそれほど速くはない:私たちが手作業でリストコンプをarray
またはSeries
にするとどうなるだろうか?
>>> %timeit df[np.array([x.startswith('t') for x in df['a']])]
10 loops, best of 3: 40.7 ms per loop
>>> %timeit df[pd.Series([x.startswith('t') for x in df['a']])]
10 loops, best of 3: 37.5 ms per loop
今、listcompが再び優勝!
結論:誰が知っていますか?しかし、timeit
の結果がなければ何も信じてはいけません。あなたがあなたが思っているものをテストしているかどうか尋ねなければなりません。
私はあなたが 'from operator import methodcaller \\ df2 ['a']。map(methodcaller(" startswith "、" t "))'がかなり早いでしょう。 – Veedrac
@TimPietzcker;それは組み込みの 'map'を使用していません(この場合は遅くなります)。 – Veedrac
@Veedrac:そうだよ。私はちょうど 'map'の第2引数がどこにあるのか疑問に思っていました。 –