Python でデータ処理を実行しようとしていますが、算術計算を行うネストされたループがあります。内側のループは 20.000 回実行されるため、次のコードは時間がかかります。
for foo in foo_list:
# get bar_list for foo
for bar in bar_list:
# do calculations w/ foo & bar
このループは、Numpy または Scipy を使用して高速化できますか?
Numpyを使用する:
import numpy as np
foo = np.array(foo_list)[:,None]
bar = np.array(bar_list)[None,:]
それで
foo + bar
または他の操作によりlen(foo) * len(bar)
、それぞれの結果を含む配列が作成されます。
例:
>>> foo_list = [10, 20, 30]
>>> bar_list = [4, 5]
>>> foo = np.array(foo_list)[:,None]
>>> bar = np.array(bar_list)[None,:]
>>> 2 * foo + bar
array([[24, 25],
[44, 45],
[64, 65]])
私は画像処理にnumpyを使用しました。for(x in row){for y in column}を使用する前(またはその逆)、あなたはその考えを理解しました。
それは小さな画像には問題ありませんでしたが、RAMを喜んで消費します。代わりに、numpy.arrayに切り替えました。はるかに高速。
これらが集計統計である場合は、Python Pandasの使用を検討してください。たとえば、すべての異なる(foo, bar)
ペアに対して何かをしたい場合は、それらのアイテムをグループ化してから、ベクトル化された NumPy 操作を適用できます。
import pandas, numpy as np
df = pandas.DataFrame(
{'foo':[1,2,3,3,5,5],
'bar':['a', 'b', 'b', 'b', 'c', 'c'],
'colA':[1,2,3,4,5,6],
'colB':[7,8,9,10,11,12]})
print df.to_string()
# Computed average of 'colA' weighted by values in 'colB', for each unique
# group of (foo, bar).
weighted_avgs = df.groupby(['foo', 'bar']).apply(lambda x: (1.0*x['colA']*x['colB']).sum()/x['colB'].sum())
print weighted_avgs.to_string()
これにより、データ オブジェクトのみについて次のように出力されます。
bar colA colB foo
0 a 1 7 1
1 b 2 8 2
2 b 3 9 3
3 b 4 10 3
4 c 5 11 5
5 c 6 12 5
これはグループ化され、集計された出力です
foo bar
1 a 1.000000
2 b 2.000000
3 b 3.526316
5 c 5.521739
ループで実際に何が起こっているかに応じて、はい。
numpy では、配列と行列を使用できます。これにより、インデックスを作成してコードの実行を高速化し、場合によってはループをなくすことができます。
索引付けの例:
import magic_square as ms
a = ms.magic(5)
print a # a is an array
[[17 24 1 8 15]
[23 5 7 14 16]
[ 4 6 13 20 22]
[10 12 19 21 3]
[11 18 25 2 9]]
# Indexing example.
b = a[a[:,1]>10]*10
print b
[[170, 240, 10, 80, 150],
[100, 120, 190, 210, 30],
[110, 180, 250, 20, 90]]
1 つまたは複数の配列を分析するときに、インデックスを作成することで速度が大幅に向上することは明らかです。強力なツールです...