回答編集履歴

3

さらについき

2018/06/14 13:05

投稿

hayataka2049
hayataka2049

スコア30933

test CHANGED
@@ -87,3 +87,21 @@
87
87
  まるごと変換する時間を関数の外に出しているので、同列に比較はできないんですが。Aがそんな頻繁に変わらないなら大丈夫でしょう。3桁速いです(データをでかくしたからなんだけど)。
88
88
 
89
89
  小手先のテクニックで多少速くしたところで、線形探索したらO(n)です。でかいデータが相手だと、でかさに比例した時間がかかります。hashにすればO(1)です。ということを考える必要があります。
90
+
91
+
92
+
93
+ ### 更に追記
94
+
95
+ ```python
96
+
97
+ print(timeit.timeit(lambda :{tuple(elem[:4]):elem[4] for elem in A}, number=1))
98
+
99
+ """ =>
100
+
101
+ 2.8804931649938226
102
+
103
+ """
104
+
105
+ ```
106
+
107
+ 100万で3秒弱。ただし1000万に増やすとメモリ消費と処理時間がすごいことになります。まあ、微妙かも。

2

追記

2018/06/14 13:05

投稿

hayataka2049
hayataka2049

スコア30933

test CHANGED
@@ -17,3 +17,73 @@
17
17
 
18
18
 
19
19
  自分でifを書くのとどっちが速いのかはやってみないとわかりませんが、まあ選択肢は色々あります。私のあのコードをなぞる必要はないです。
20
+
21
+
22
+
23
+ ### この質問とはあまり関係のないアドバイス
24
+
25
+ 前回の質問は「numpy配列から探せ」という注文だったから、あえて書かなかったんですが、速さを求めるなら、たとえばこういうアプローチがあります。
26
+
27
+
28
+
29
+ ```python
30
+
31
+ import timeit
32
+
33
+ import numpy as np
34
+
35
+
36
+
37
+ A = np.arange(5000000).reshape((1000000, 5)) # 注目
38
+
39
+
40
+
41
+ def fa(a,b,c,d):
42
+
43
+ """
44
+
45
+ 前回の回答の方式
46
+
47
+ """
48
+
49
+ tmp = A
50
+
51
+ for i, eqv in enumerate([a,b,c,d]):
52
+
53
+ tmp = tmp[tmp[:,i] == eqv]
54
+
55
+
56
+
57
+ tmp[:,-1]
58
+
59
+
60
+
61
+ # 予めまるごとdictに変換しておけば極めて有利
62
+
63
+ hashdic = {tuple(elem[:4]):elem[4] for elem in A}
64
+
65
+ def fb(a,b,c,d):
66
+
67
+ hashdic.get((a,b,c,d))
68
+
69
+
70
+
71
+ print(timeit.timeit(lambda : fa(0,1,2,3), number=1000))
72
+
73
+ print(timeit.timeit(lambda : fb(0,1,2,3), number=1000))
74
+
75
+ """ =>
76
+
77
+ 6.048210394001217
78
+
79
+ 0.0035514350020093843 # すごーい
80
+
81
+ """
82
+
83
+ ```
84
+
85
+
86
+
87
+ まるごと変換する時間を関数の外に出しているので、同列に比較はできないんですが。Aがそんな頻繁に変わらないなら大丈夫でしょう。3桁速いです(データをでかくしたからなんだけど)。
88
+
89
+ 小手先のテクニックで多少速くしたところで、線形探索したらO(n)です。でかいデータが相手だと、でかさに比例した時間がかかります。hashにすればO(1)です。ということを考える必要があります。

1

追記

2018/06/14 12:58

投稿

hayataka2049
hayataka2049

スコア30933

test CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
 
8
8
 
9
- 逆に、私がnumpyで書いた方法はループごとにスライスして動的メモリ確保して、と余計なオーバーヘッドがあるので、恐らくCで同じことをやっても遅いです。python+numpyだと素直にやったのでは性能が出ないので、トリッキーな方法を取りましたが。あれはnumpyで行の比較を短絡評価する方法が探しても見つからなかったので、ああいうコードにした次第です。
9
+ 逆に、私がnumpyで書いた方法はループごとにスライスして動的メモリ確保して、と余計なオーバーヘッドがあるので、(書けたとして)恐らくCで同じことをやっても遅いです。python+numpyだと素直にやったのでは性能が出ないので、トリッキーな方法を取りましたが。あれはnumpyで行の比較を短絡評価する方法が探しても見つからなかったので、ああいうコードにした次第です。
10
10
 
11
11
 
12
12