それ,numpy で書かない?
Python ではリストがよく使われる。また,for ループが遅いのでリストに特化したリスト内包表記も推奨されることが多い。
それなりの根拠があるからではあるが...
課題:[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]] のような二重リストを作る。
[n×n, 2] の二重リストを trial 回作成し,処理時間の平均値と標準偏差を記録する。
from statistics import mean, stdev
from time import time
n = 1000
trial = 100
二重の for ループと append()
def for_loop(n):
start = time()
list1 = []
for y in range(n):
for x in range(n):
list1.append([y, x])
return time() - start
for_loop_times = [for_loop(n) for i in range(trial)]
print(f"二重for文 平均値: {mean(for_loop_times): .3f}, 標準偏差: {stdev(for_loop_times): .3f}")
二重for文 平均値: 0.255, 標準偏差: 0.019
リスト内包表記で
def comprehension(n):
start = time()
list1 = [[y, x] for y in range(n) for x in range(n)]
return time() - start
comprehension_times = [comprehension(n) for i in range(trial)]
print(f"comprehension 平均値: {mean(comprehension_times): .3f}, 標準偏差: {stdev(comprehension_times): .3f}")
comprehension 平均値: 0.252, 標準偏差: 0.018
numpy で 二重 for ループ
import numpy as np
def numpy(n):
start = time()
a = np.zeros((n**2, 2), dtype=int)
for i in range(n**2):
a[i, 0] = i / n
a[i, 1] = i % n
return time() - start
numpy_times = [numpy(n) for i in range(trial)]
print(f"numpy 平均値: {mean(numpy_times): .3f}, 標準偏差: {stdev(numpy_times): .3f}")
numpy 平均値: 0.162, 標準偏差: 0.001
numpy で 二重 for ループ(その2)
def numpy2(n):
start = time()
a = np.zeros((n**2, 2), dtype=int)
for i in range(n):
i0 = i*n
for j in range(n):
a[i0+j, 0] = i
a[i0+j, 1] = j
return time() - start
numpy_times2 = [numpy2(n) for i in range(trial)]
print(f"numpy2 平均値: {mean(numpy_times2): .3f}, 標準偏差: {stdev(numpy_times2): .3f}")
numpy2 平均値: 0.153, 標準偏差: 0.004
numpy, itertools を使う
一行で書ける。
import itertools
def numpy3(n):
start = time()
a = np.array(list(itertools.product(range(n), repeat=2)))
return time() - start
numpy_times3 = [numpy3(n) for i in range(trial)]
print(f"numpy3 平均値: {mean(numpy_times3): .3f}, 標準偏差: {stdev(numpy_times3): .3f}")
numpy3 平均値: 0.193, 標準偏差: 0.004
結論
numpy() は for を使っても十分に速い。