画像にあるような1列のnumpy配列の中から13と10が連続して続く箇所を検索し、その次から8個分のデータを抜き出して別の変数に格納する方法を教えていただきたいです。(それを配列が終わるまで繰り返して抜き出した8つのデータを1列とした行列を作りたい)
numpy配列の中からある値とある値が連続している箇所を検索する、というところから躓いておりなかなか前に進めない状況です、、
ざっくりとした質問で申し訳ありませんが、どなたか教えていただけると助かります。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
Numpyには便利なベクトル化された関数・メソッドがたくさん実装されています。
ベクトル化された関数・メソッドを用いることで、Python標準のfor文を用いるよりも効率よく処理することができます。
python
1def extract(arr, v, n): 2 """ 3 arr : 検索元の配列(1次元ndarray) 4 v: 検索する配列(1次元のarray-like) 5 n: 取り出す個数(int) 6 """ 7 vln = len(v) 8 base = (arr.max()+1) ** np.arange(vln) 9 search_idx, = np.nonzero(np.convolve(arr, base) == np.sum(base*v[::-1])) 10 idx = search_idx + np.arange(1, n+1)[:, None] 11 return arr[idx]
python
1# 実行例 2In [11]: rn = np.random.RandomState(0) 3 ...: arr = rn.randint(0, 100, 100000) 4 ...: extract(arr, [13, 10], 8) 5Out[11]: 6array([[60, 80, 13, 98, 80, 72, 25, 10, 21, 0], 7 [61, 21, 10, 57, 80, 81, 68, 12, 19, 53], 8 [21, 84, 98, 45, 74, 23, 74, 95, 55, 35], 9 [48, 80, 57, 30, 32, 27, 36, 76, 27, 79], 10 [87, 36, 45, 85, 51, 51, 88, 70, 22, 5], 11 [76, 51, 30, 45, 33, 78, 94, 55, 20, 84], 12 [35, 49, 85, 35, 49, 20, 21, 88, 82, 0], 13 [93, 16, 45, 68, 55, 23, 1, 25, 35, 21]]) 14 15# @aokikenichi さんの作成した配列に対して 16In [12]: l = [0, 1, 2, 3, 17 ...: 13, 10, 5, 4, 3, 2, 1, 0, 18 ...: 13, 10, 1, 2, 3, 4, 5, 6, 7, 19 ...: 13, 10, 99, 98, 97, 96, 95, 94, 20 ...: 13, 10, 100, 101, 102, 103, 104, 105] 21 ...: extract(np.array(l), [13, 10], 3) 22Out[12]: 23array([[ 5, 1, 99, 100], 24 [ 4, 2, 98, 101], 25 [ 3, 3, 97, 102]]) 26 27# 条件を変えることもできます 28In [13]: extract(np.array(l), [1, 2, 3], 4) 29Out[13]: 30array([[13, 4], 31 [10, 5], 32 [ 5, 6], 33 [ 4, 7]])
@aokikenichi さんの回答は一般化すると以下のような関数になりますが、
python
1def extract_for(l, v, n): 2 vln = len(v) 3 out = [] 4 for i in range(len(l) - 1): 5 if all(l[i+j] == vi for j, vi in enumerate(v)): 6 out.append(l[i+vln:i+vln+n]) 7 return np.array(out).T
速度を比較するとNumpyの関数を用いたほうが効率が良いことがわかります。
python
1# arrは長さ100000の配列 2In [21]: %timeit extract(arr, [13, 10], 8) 3698 µs ± 15.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 4 5In [22]: l = arr.tolist() 6 ...: %timeit extract_for(l, [13, 10], 8) 778 ms ± 1.32 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
投稿2021/04/21 04:07
編集2021/04/21 07:16総合スコア1399
0
ベストアンサー
Python
1l = [0, 1, 2, 3, 13, 10, 5, 4, 3, 2, 1, 0, 13, 10, 1, 2, 3, 4, 5, 6, 7, 13, 10, 99, 98, 97, 96, 95, 94, 13, 10, 100, 101, 102, 103, 104, 105] 2 3out = [] 4for i in range(len(l) - 1): 5 if l[i] == 13 and l[i + 1] == 10: 6 out.append(l[i + 2]) 7 out.append(l[i + 3]) 8 out.append(l[i + 4]) 9print(out)
[5, 4, 3, 1, 2, 3, 99, 98, 97, 100, 101, 102]
入力リストを作るのが面倒なので適当に作成し、8個先までではなくて3個先までにしました。
1列とした行列を作りたい
だが例示されたものは3列の行列 なところが分かりませんが 大体こんな感じでは無いですか?
投稿2021/04/20 13:43
総合スコア2235
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。