pandasの効率的な書き方
なるべくforを使わない
pandasのベースはnumpyなので、numpyのテクニックが有効です。
例として、下記の表xの行の積の和を求めたいとします。
jupyter
x = pd.DataFrame(np.random.rand(100000,3),columns=list('abc'))
x[:3] # 先頭3行
a | b | c | |
---|---|---|---|
0 | 0.902417 | 0.443804 | 0.678391 |
1 | 0.873176 | 0.405184 | 0.845241 |
2 | 0.050312 | 0.040537 | 0.686412 |
下記のように for を使うことなく計算できます。
jupyter
%%time
print((x.a*x.b*x.c).sum())
>>>
12501.777226525046
Wall time: 7 ms
DataFrameやSeriesを通して頻繁にアクセスしない
先ほどの例で、forで行ベースで計算しないといけない場合も、工夫次第で高速化できます。
行ベースで、よく使うのは、iterrows() でしょう。
jupyter
%%time
s = 0
for _,r in x.iterrows():
s += r.a*r.b*r.c
print(s)
>>>
12501.7772265
Wall time: 5.71 s
forを使わない場合より 3桁遅いです。
DataFrameは、列(Series)で構成されているので、各Seriesをzipにした方が、まだ高速です。
jupyter
%%time
s = 0
for a,b,c in zip(x.a,x.b,x.c):
s += a*b*c
print(s)
>>>
12501.7772265
Wall time: 111 ms
次によく使うのは、index参照でしょう。
jupyter
%%time
s = 0
for i in range(len(x)):
s += x.a[i]*x.b[i]*x.c[i]
print(s)
>>>
12501.7772265
Wall time: 4.59 s
速度的には、iterrows()と同じくらいです。
Seriesを通すと遅いので、先にlistにすると高速化できます。
jupyter
%%time
s = 0
a,b,c = x.a.tolist(),x.b.tolist(),x.c.tolist()
for i in range(len(x)):
s += a[i]*b[i]*c[i]
print(s)
>>>
12501.777226525046
Wall time: 66 ms
以上