python
1import io
2import numpy as np
3from scipy import ndimage
4
5data = """
68,17,22,23,24,25,37,40,44,45
712,13,17,19,22,23,24,25,30,33
83,9,11,18,24,31,32,39,49,55
91,5,10,11,12,13,20,25,30,35
105,7,15,16,18,20,27,39,53,59
113,4,9,16,17,21,22,23,35,47
1213,14,15,16,24,25,28,29,37,44
134,6,7,15,21,22,33,34,35,36
146,11,12,20,22,24,29,34,37,40
151,3,6,8,11,21,22,23,24,25"""
16
17arr = np.genfromtxt(io.StringIO(data), delimiter=',')
18# array([[ 8, 17, 22, 23, 24, 25, 37, 40, 44, 45],
19# [12, 13, 17, 19, 22, 23, 24, 25, 30, 33],
20# [ 3, 9, 11, 18, 24, 31, 32, 39, 49, 55],
21# [ 1, 5, 10, 11, 12, 13, 20, 25, 30, 35],
22# [ 5, 7, 15, 16, 18, 20, 27, 39, 53, 59],
23# [ 3, 4, 9, 16, 17, 21, 22, 23, 35, 47],
24# [13, 14, 15, 16, 24, 25, 28, 29, 37, 44],
25# [ 4, 6, 7, 15, 21, 22, 33, 34, 35, 36],
26# [ 6, 11, 12, 20, 22, 24, 29, 34, 37, 40],
27# [ 1, 3, 6, 8, 11, 21, 22, 23, 24, 25]])
28
29# その1
30idx = np.all(np.convolve(np.ediff1d(arr.ravel()) == 1, np.array([1, 1, 1]))[:-1].reshape(arr.shape)[:, 2:-1] != 3, 1)
31# その2
32idx = np.all(ndimage.convolve((np.diff(arr) == 1).view(np.int8), np.array([[1, 1, 1]])) != 3, 1)
33
34arr[idx]
35# array([[ 3, 9, 11, 18, 24, 31, 32, 39, 49, 55],
36# [ 5, 7, 15, 16, 18, 20, 27, 39, 53, 59],
37# [ 3, 4, 9, 16, 17, 21, 22, 23, 35, 47],
38# [ 6, 11, 12, 20, 22, 24, 29, 34, 37, 40]])
解説
工程1
まず、np.diff()
あるいはnp.ediff1d()
を用いて、隣との差を計算します。np.ediff1d()
を用いる場合は、事前にarr
を一次元配列にします。
python
1a = np.diff(arr)
2# array([[ 9, 5, 1, 1, 1, 12, 3, 4, 1],
3# [ 1, 4, 2, 3, 1, 1, 1, 5, 3],
4# [ 6, 2, 7, 6, 7, 1, 7, 10, 6],
5# [ 4, 5, 1, 1, 1, 7, 5, 5, 5],
6# [ 2, 8, 1, 2, 2, 7, 12, 14, 6],
7# [ 1, 5, 7, 1, 4, 1, 1, 12, 12],
8# [ 1, 1, 1, 8, 1, 3, 1, 8, 7],
9# [ 2, 1, 8, 6, 1, 11, 1, 1, 1],
10# [ 5, 1, 8, 2, 2, 5, 5, 3, 3],
11# [ 2, 3, 2, 3, 10, 1, 1, 1, 1]])
12
13a1D = np.ediff1d(arr.ravel())
14# array([ 9, 5, 1, 1, 1, 12, 3, 4, 1, -33, 1, 4, 2,
15# 3, 1, 1, 1, 5, 3, -30, 6, 2, 7, 6, 7, 1,
16# 7, 10, 6, -54, 4, 5, 1, 1, 1, 7, 5, 5, 5,
17# -30, 2, 8, 1, 2, 2, 7, 12, 14, 6, -56, 1, 5,
18# 7, 1, 4, 1, 1, 12, 12, -34, 1, 1, 1, 8, 1,
19# 3, 1, 8, 7, -40, 2, 1, 8, 6, 1, 11, 1, 1,
20# 1, -30, 5, 1, 8, 2, 2, 5, 5, 3, 3, -39, 2,
21# 3, 2, 3, 10, 1, 1, 1, 1])
工程2
続いて、得た配列を1と比較することで、連番になっている部分を取得します。(.view(np.int8)
は、True/Falseの配列を1/0にするために用いています)
python
1b = (a == 1).view(np.int8)
2# array([[0, 0, 1, 1, 1, 0, 0, 0, 1],
3# [1, 0, 0, 0, 1, 1, 1, 0, 0],
4# [0, 0, 0, 0, 0, 1, 0, 0, 0],
5# [0, 0, 1, 1, 1, 0, 0, 0, 0],
6# [0, 0, 1, 0, 0, 0, 0, 0, 0],
7# [1, 0, 0, 1, 0, 1, 1, 0, 0],
8# [1, 1, 1, 0, 1, 0, 1, 0, 0],
9# [0, 1, 0, 0, 1, 0, 1, 1, 1],
10# [0, 1, 0, 0, 0, 0, 0, 0, 0],
11# [0, 0, 0, 0, 0, 1, 1, 1, 1]], dtype=int8)
12
13b1D = a1D == 1
14# array([False, False, True, True, True, False, False, False, True,
15# False, True, False, False, False, True, True, True, False,
16# False, False, False, False, False, False, False, True, False,
17# False, False, False, False, False, True, True, True, False,
18# False, False, False, False, False, False, True, False, False,
19# False, False, False, False, False, True, False, False, True,
20# False, True, True, False, False, False, True, True, True,
21# False, True, False, True, False, False, False, False, True,
22# False, False, True, False, True, True, True, False, False,
23# True, False, False, False, False, False, False, False, False,
24# False, False, False, False, False, True, True, True, True])
上記の配列で1が3連続する箇所は、連番が4つ続いているということです。
工程3
畳み込み演算(np.convolve()
またはscipy.ndimage.convolve()
)を利用して、1が3連続する箇所を探し出します。なおnp.convolve()
は一次元配列同士でしか計算できませんので、計算後に形を整える必要があります。
python
1c = ndimage.convolve(b, np.array([[1, 1, 1]]))
2# array([[0, 1, 2, 3, 2, 1, 0, 1, 2],
3# [2, 1, 0, 1, 2, 3, 2, 1, 0],
4# [0, 0, 0, 0, 1, 1, 1, 0, 0],
5# [0, 1, 2, 3, 2, 1, 0, 0, 0],
6# [0, 1, 1, 1, 0, 0, 0, 0, 0],
7# [2, 1, 1, 1, 2, 2, 2, 1, 0],
8# [3, 3, 2, 2, 1, 2, 1, 1, 0],
9# [1, 1, 1, 1, 1, 2, 2, 3, 3],
10# [1, 1, 1, 0, 0, 0, 0, 0, 0],
11# [0, 0, 0, 0, 1, 2, 3, 3, 3]], dtype=int8)
12
13c1D = np.convolve(b1D, np.array([1, 1, 1]))[:-1].reshape(arr.shape)[:, 2:-1]
14# array([[1, 2, 3, 2, 1, 0, 1],
15# [1, 0, 1, 2, 3, 2, 1],
16# [0, 0, 0, 1, 1, 1, 0],
17# [1, 2, 3, 2, 1, 0, 0],
18# [1, 1, 1, 0, 0, 0, 0],
19# [1, 1, 1, 2, 2, 2, 1],
20# [3, 2, 2, 1, 2, 1, 1],
21# [1, 1, 1, 1, 2, 2, 3],
22# [1, 1, 0, 0, 0, 0, 0],
23# [0, 0, 0, 1, 2, 3, 3]])
上記の配列で3
がある箇所は、連番が4つ続いているということです。
工程4
取得した配列に3が含まれる行を除外するので、求めるidx
は、
python
1idx = np.all(c != 3, 1)
2# array([False, False, True, False, True, True, False, False, True, False])
3
4idx = np.all(c1D != 3, 1)
5# array([False, False, True, False, True, True, False, False, True, False])
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。