回答編集履歴
3
追記
answer
CHANGED
@@ -26,7 +26,8 @@
|
|
26
26
|
たとえば、
|
27
27
|
|
28
28
|
```python
|
29
|
-
s = pd.Series([10, 10, 10, 12,
|
29
|
+
s = pd.Series([10, 10, 10, 12, 13, 13, 0, 0, 10, 12, 13, 10, 12, 10, 12, 13, 13])
|
30
|
+
# [10, 10, 10, 12, 13, 13, 10, 12, 13, , 10, 12, 13, 13]
|
30
31
|
v = np.array([10, 12, 13])
|
31
32
|
|
32
33
|
function(s.to_numpy(), v)
|
@@ -35,12 +36,94 @@
|
|
35
36
|
# 1 10 1
|
36
37
|
# 2 10 1
|
37
38
|
# 3 12 1
|
38
|
-
# 4
|
39
|
+
# 4 13 1
|
39
|
-
# 5
|
40
|
+
# 5 13 1
|
40
|
-
# 6
|
41
|
+
# 6 10 2
|
41
|
-
# 7
|
42
|
+
# 7 12 2
|
42
|
-
# 8 13
|
43
|
+
# 8 13 2
|
43
|
-
# 9 10
|
44
|
+
# 9 10 3
|
44
|
-
# 10 12
|
45
|
+
# 10 12 3
|
45
|
-
# 11 13
|
46
|
+
# 11 13 3
|
47
|
+
# 12 13 3
|
48
|
+
```
|
49
|
+
|
50
|
+
## 挙動の解説
|
51
|
+
|
52
|
+
### 1. 同じ値が連続する部分の除外
|
53
|
+
|
54
|
+
「`10,12,13`はどれくらい連続しているか分からない」ということなので、同じ数が連続する部分をひとまとめにします。これは、インデックスを一つずらした配列と比較することで取得できます。
|
55
|
+
|
56
|
+
```python
|
57
|
+
cut_index, = np.r_[True, a[1:] != a[:-1], True].nonzero()
|
58
|
+
short_a = a[cut_index[:-1]]
|
59
|
+
|
60
|
+
"""
|
61
|
+
a : [10, 10, 10, 12, 13, 13, 0, 0, 10, 12, 13, 10, 12, 10, 12, 13, 13]
|
62
|
+
|
63
|
+
a[1:] : 10 [10, 10, 12, 13, 13, 0, 0, 10, 12, 13, 10, 12, 10, 12, 13, 13]
|
64
|
+
a[:-1] : [10, 10, 10, 12, 13, 13, 0, 0, 10, 12, 13, 10, 12, 10, 12, 13] 13
|
65
|
+
a[1:] != a[:-1] : [ F, F, T, T, F, T, F, T, T, T, T, T, T, T, T, F]
|
66
|
+
(concatenate) : [ T, F, F, T, T, F, T, F, T, T, T, T, T, T, T, T, F, T]
|
67
|
+
|
68
|
+
cut_index : [ 0, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 17]
|
69
|
+
short_a : [10, 12, 13, 0, 10, 12, 13, 10, 12, 10, 12, 13, ]
|
70
|
+
"""
|
71
|
+
```
|
72
|
+
|
73
|
+
### 2. 一致箇所の検索
|
74
|
+
|
75
|
+
前節で作成した配列`short_a`から、`10,12,13`のまとまりを探します。
|
76
|
+
そのためにまず、`short_a`を3つずつ区切るためのインデックスを作成します。
|
77
|
+
|
78
|
+
```python
|
79
|
+
slide_index = np.arange(short_a.size-v_size+1)[:, None] + np.arange(v_size)
|
80
|
+
print(slide_index)
|
81
|
+
# [[ 0 1 2]
|
82
|
+
# [ 1 2 3]
|
83
|
+
# [ 2 3 4]
|
84
|
+
# ...
|
85
|
+
# [ 7 8 9]
|
86
|
+
# [ 8 9 10]
|
87
|
+
# [ 9 10 11]]
|
88
|
+
```
|
89
|
+
|
90
|
+
`v`と比較することで、`10,12,13`と一致する箇所を探します。
|
91
|
+
|
92
|
+
```python
|
93
|
+
match = (short_a[slide_index] == v).all(1)
|
94
|
+
|
95
|
+
"""
|
96
|
+
slide_a : [[10, 12, 13], [12, 13, 0], [13, 0, 10], [ 0, 10, 12], [10, 12, 13], ...]
|
97
|
+
v : [[10, 12, 13], [ > ], [ > ], [ > ], [ > ], ...]
|
98
|
+
match : [ True, False, False, False, True, ...]
|
99
|
+
"""
|
100
|
+
```
|
101
|
+
|
102
|
+
`match`で得られた`True`は、`10,12,13`の`10`の位置のみなので、`np.convolve()`を利用して`10,12,13`の位置が`True`になるようにします。
|
103
|
+
|
104
|
+
```python
|
105
|
+
all_match = np.convolve(match, np.ones(v_size, dtype=int))
|
106
|
+
|
107
|
+
"""
|
108
|
+
short_a : [10, 12, 13, 0, 10, 12, 13, 10, 12, 10, 12, 13]
|
109
|
+
match : [ T, F, F, F, T, F, F, F, F, T]
|
110
|
+
all_match : [ 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1]
|
111
|
+
"""
|
112
|
+
```
|
113
|
+
|
114
|
+
### 3. 一致箇所の拡大復元
|
115
|
+
|
116
|
+
前節で求めた`all_match`は、`10,10,10`のように同じ値が連続する部分がまとまった配列に対する位置なので、`np.repeat()`を用いて1.の逆を行います。
|
117
|
+
|
118
|
+
```python
|
119
|
+
index, = np.repeat(all_match, np.ediff1d(cut_index)).nonzero()
|
120
|
+
|
121
|
+
"""
|
122
|
+
a : [10, 10, 10, 12, 13, 13, 0, 0, 10, 12, 13, 10, 12, 10, 12, 13, 13]
|
123
|
+
cut_index : [ 0, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 17]
|
124
|
+
|
125
|
+
all_match : [ 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, ]
|
126
|
+
(repeat) : [ 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1]
|
127
|
+
index : [ 0, 1, 2, 3, 4, 5, 8, 9, 10, 13, 14, 15, 16]
|
128
|
+
"""
|
46
129
|
```
|
2
微修正
answer
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
result_array = a[index]
|
19
19
|
result_index = np.isin(index, cut_index[match.nonzero()[0]]).cumsum()
|
20
20
|
|
21
|
-
return pd.DataFrame({'
|
21
|
+
return pd.DataFrame({'num': result_array, 'id': result_index})
|
22
22
|
```
|
23
23
|
|
24
24
|
第一引数には対象のシリーズをnumpy配列に変換したものを、
|
@@ -30,17 +30,17 @@
|
|
30
30
|
v = np.array([10, 12, 13])
|
31
31
|
|
32
32
|
function(s.to_numpy(), v)
|
33
|
-
#
|
33
|
+
# num id
|
34
|
-
# 0
|
34
|
+
# 0 10 1
|
35
|
-
# 1
|
35
|
+
# 1 10 1
|
36
|
-
# 2
|
36
|
+
# 2 10 1
|
37
|
-
# 3
|
37
|
+
# 3 12 1
|
38
|
-
# 4
|
38
|
+
# 4 12 1
|
39
|
-
# 5
|
39
|
+
# 5 12 1
|
40
|
-
# 6
|
40
|
+
# 6 13 1
|
41
|
-
# 7
|
41
|
+
# 7 13 1
|
42
|
-
# 8
|
42
|
+
# 8 13 1
|
43
|
-
# 9
|
43
|
+
# 9 10 2
|
44
|
-
# 10
|
44
|
+
# 10 12 2
|
45
|
-
# 11
|
45
|
+
# 11 13 2
|
46
46
|
```
|
1
微修正
answer
CHANGED
@@ -10,10 +10,10 @@
|
|
10
10
|
|
11
11
|
cut_index, = np.r_[True, a[1:] != a[:-1], True].nonzero()
|
12
12
|
short_a = a[cut_index[:-1]]
|
13
|
-
slide_index = np.arange(short_a.size-
|
13
|
+
slide_index = np.arange(short_a.size-v_size+1)[:, None] + np.arange(v_size)
|
14
14
|
match = (short_a[slide_index] == v).all(1)
|
15
15
|
all_match = np.convolve(match, np.ones(v_size, dtype=int))
|
16
|
-
index = np.repeat(all_match, np.ediff1d(cut_index)).nonzero()
|
16
|
+
index, = np.repeat(all_match, np.ediff1d(cut_index)).nonzero()
|
17
17
|
|
18
18
|
result_array = a[index]
|
19
19
|
result_index = np.isin(index, cut_index[match.nonzero()[0]]).cumsum()
|