質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3717閲覧

多次元配列でのnp.appendをlist appendを用いて高速化したい

loreeeee

総合スコア40

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/07/03 06:38

編集2018/07/03 08:46

以下のコードは(z, y, x) = (1,100,200)の配列をz方向に100回appendするコードです.
n_loops = 100で実行時間は0.15[sec]なのですが,配列サイズを大きくしたり,n_loops=10000にすると途方もない時間がかかってしまいます.
そこでnp.appendをlist appendに変換すると早いと知り実装しようとしたのですが,list appendではaxisの指定が分からずとまってしまいました.
どなたか教えていただけないでしょうか?

python

1import time 2import numpy as np 3 4data = np.empty((1,100,200)) 5n_loops = 100 6 7#np.append 8start_time = time.time() 9for _ in range(n_loops): 10 bbb = np.random.randint(low=1, high=5,size=1*100*200).reshape(1,100,200) 11 data = np.append(data, bbb, axis=0) 12end_time = time.time() 13 14print(str(end_time - start_time) + ' [sec]') #print calculation time

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2018/07/03 06:44

最初から(n_loops,100,200)の配列を用意すれば良いんじゃないですかね
loreeeee

2018/07/03 06:55 編集

元のデータの配列サイズが実際にはさらに巨大なため,handlingしやすいように元データは小分けにしている事情があります.
guest

回答1

0

ベストアンサー

そこでnp.appendをlist appendに変換すると早いと知り

誰だ、そんなこと言ったの・・・まあ確かに、ループのたびにオブジェクト作り直しで足していくよりは速いかもしれませんが。

「最初から(n_loops,100,200)の配列を用意すれば良い」という指摘がすでに上がっていますが、とりあえず、配列の連結がどうしても必要なら、

python

1import time 2import numpy as np 3 4data = np.empty((1,100,200)) 5n_loops = 1000 6 7# np.append 8start_time = time.time() 9for _ in range(n_loops): 10 bbb = np.random.randint(low=1, high=5,size=1*100*200).reshape(1,100,200) 11 data = np.append(data, bbb, axis=0) 12end_time = time.time() 13print(data.shape) 14print(str(end_time - start_time) + ' [sec]') #print calculation time 15""" => 16(1001, 100, 200) 1725.065351009368896 [sec] 18""" 19 20# listに入れてまとめてnp.concatenate 21start_time = time.time() 22lst = [] 23for _ in range(n_loops): 24 bbb = np.random.randint(low=1, high=5,size=1*100*200).reshape(1,100,200) 25 lst.append(bbb) 26data = np.concatenate(lst, axis=0) 27end_time = time.time() 28 29print(data.shape) 30print(str(end_time - start_time) + ' [sec]') #print calculation time 31""" => 32(1000, 100, 200) 330.22292709350585938 [sec] 34"""

listに入れておいて、最後にまとめてnp.concatenateを呼ぶ。これで実用的な速度になるでしょう。

追記

python

1# 空の配列を先に定義しておく 2data = np.empty((n_loops,100,200)) 3start_time = time.time() 4for i in range(n_loops): 5 bbb = np.random.randint(low=1, high=5,size=1*100*200).reshape(1,100,200) 6 data[i] = bbb 7end_time = time.time() 8 9print(data.shape) 10print(str(end_time - start_time) + ' [sec]') #print calculation time 11""" => 12(1000, 100, 200) 130.16308903694152832 [sec] 14"""

こっちの方が速い・・・かな?

投稿2018/07/03 06:52

編集2018/07/03 07:39
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2018/07/03 07:37 編集

なるほど。まあ、意図してることはわかりますが、最適な方法かと言われると微妙な気が・・・
hayataka2049

2018/07/03 07:40 編集

可変長の要求がなければ、今追記に書いた方法の方が微妙に良さそうです。メモリ消費も約半分で済みそうですし
loreeeee

2018/07/03 08:39

hayataka2049さん,丁寧に回答して頂きありがとうございます.np.concatenateの方法で解決できました.横レスで申し訳ないのですが,メモリ消費量が半分で済むとありますが,メモリの消費量はどうやって確認できるのでしょうか?
hayataka2049

2018/07/03 08:45

memory_profilerなどのメモリプロファイラを回すと見れます
loreeeee

2018/07/03 08:49

ありがとうございます.一度確認してみます.
hayataka2049

2018/07/03 08:58

手元でも今やってみて、確かに減ることは確認しました。1つのコード内に複数の関数を定義して書くとちょっと面倒くさいので、ファイルを分けた方が無難っぽいです
mkgrei

2018/07/03 12:07

> https://deepage.net/features/numpy-append.html これはもはや悪質ですね… 同じようなネタを一つ。 np.arrayよりlistの方が和の計算がはやいです。 import time import numpy as np n = 100000 a = np.arange(n) b = list(range(n)) s = time.time() ans = sum(a) print(time.time() - s) -> 0.011241912841796875 s s = time.time() ans = sum(b) print(time.time() - s) -> 0.0017781257629394531 s 理由はnp.sumを使っていないので、np.arrayを一度listにキャストしています。 s = time.time() ans = np.sum(a) print(time.time() - s) -> 0.00035858154296875 s ネットの情報は鵜呑みにしてはいけない…
loreeeee

2018/07/04 03:39

mkgreiさん,補足ありがとうございます.なるほど,型を意識してコードを組まないと余計に遅くなってしまうのですね...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問