teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

挿入ソート版追記

2019/02/14 02:29

投稿

8524ba23
8524ba23

スコア38352

answer CHANGED
@@ -144,4 +144,83 @@
144
144
  [ 3. 6. nan nan nan]
145
145
  [ 4. 7. nan nan nan]]
146
146
  """
147
+ ```
148
+ 挿入ソート版
149
+ -----
150
+ 題意から以下の処理でもよさそうです。
151
+ 再帰版よりもはるかに速く処理できます。
152
+
153
+ ```Python
154
+ import numpy as np
155
+ import pprint
156
+
157
+ import pandas as pd
158
+ from io import StringIO
159
+ f = StringIO("""c1,c2,c3,c4,c5
160
+ ,,7,8,
161
+ 1,2,,,
162
+ ,,6,6,
163
+ 4,7,,,
164
+ ,,,2,1
165
+ ,,,7,4
166
+ 6,9,,,
167
+ ,1,2,,
168
+ ,,,9,5
169
+ ,4,4,,
170
+ ,,1,1,
171
+ 2,3,,,
172
+ 5,8,,,
173
+ ,,,3,2
174
+ ,,3,4,
175
+ ,5,5,,
176
+ ,,,5,3
177
+ 3,6,,,""")
178
+ ary = pd.read_csv(f).values.tolist()
179
+
180
+
181
+ ret = []
182
+
183
+ # 各列について左から順に処理
184
+ col_cnt = len(ary[0])
185
+ for c in range(col_cnt):
186
+
187
+ # 対象列がnanでない行のみ抜き出す
188
+ rows = []
189
+ for r in ary[::-1]:
190
+ if not np.isnan(r[c]):
191
+ rows.append(r)
192
+ ary.remove(r)
193
+
194
+ # 結果配列に列値が昇順になるように挿入していく
195
+ for row in rows:
196
+ is_ins = False
197
+ for idx,ret_row in enumerate(ret):
198
+ if row[c] < ret_row[c]:
199
+ ret.insert(idx,row)
200
+ is_ins = True
201
+ break
202
+ if not is_ins:
203
+ ret.append(row)
204
+
205
+ pprint.pprint(ret)
206
+ """
207
+ [[nan, nan, 1.0, 1.0, nan],
208
+ [nan, 1.0, 2.0, nan, nan],
209
+ [1.0, 2.0, nan, nan, nan],
210
+ [2.0, 3.0, nan, nan, nan],
211
+ [nan, nan, nan, 2.0, 1.0],
212
+ [nan, nan, nan, 3.0, 2.0],
213
+ [nan, nan, 3.0, 4.0, nan],
214
+ [nan, 4.0, 4.0, nan, nan],
215
+ [nan, 5.0, 5.0, nan, nan],
216
+ [3.0, 6.0, nan, nan, nan],
217
+ [4.0, 7.0, nan, nan, nan],
218
+ [5.0, 8.0, nan, nan, nan],
219
+ [6.0, 9.0, nan, nan, nan],
220
+ [nan, nan, nan, 5.0, 3.0],
221
+ [nan, nan, 6.0, 6.0, nan],
222
+ [nan, nan, nan, 7.0, 4.0],
223
+ [nan, nan, 7.0, 8.0, nan],
224
+ [nan, nan, nan, 9.0, 5.0]]
225
+ """
147
226
  ```

1

再帰版を追記

2019/02/14 02:29

投稿

8524ba23
8524ba23

スコア38352

answer CHANGED
@@ -57,4 +57,91 @@
57
57
  [nan 4. 4. nan nan]
58
58
  [nan nan nan 3. 2.]]
59
59
  """
60
+ ```
61
+
62
+
63
+ 再帰版
64
+ -----
65
+
66
+ 総当たりよりは速いですが、15行程度が限界ですね。
67
+ ```Python
68
+
69
+ import numpy as np
70
+
71
+ def search( ary):
72
+ row_cnt = ary.shape[0]
73
+ col_cnt = ary.shape[1]
74
+
75
+ # 条件を満たすか
76
+ # row : 行の位置
77
+ # mins : 現時点の各列の最小値
78
+ def is_match(row,mins):
79
+ for col in range(col_cnt):
80
+ v = ary[row,col]
81
+ if np.isnan(v):
82
+ continue
83
+ if v < mins[col]:
84
+ return False
85
+ mins[col] = v # 最小値を更新
86
+ return True
87
+
88
+ # rows : 行位置の配列
89
+ # mins : 現時点の各列の最小値
90
+ def search_row(rows,mins):
91
+ if len(rows) == row_cnt:
92
+ return rows
93
+
94
+ rows_set = set(rows)
95
+ for row in range(row_cnt):
96
+ if row in rows_set: # 重複は除く
97
+ continue
98
+ next_mins = mins.copy()
99
+ if is_match(row,next_mins):
100
+ ret = search_row(rows+[row],next_mins)
101
+ if ret:
102
+ return ret
103
+
104
+ rows = search_row([],np.zeros(col_cnt))
105
+ return ary[rows,:]
106
+
107
+
108
+ import pandas as pd
109
+ from io import StringIO
110
+ f = StringIO("""c1,c2,c3,c4,c5
111
+ ,,7,8,
112
+ 1,2,,,
113
+ ,,6,6,
114
+ 4,7,,,
115
+ ,,,2,1
116
+ ,,,7,4
117
+ ,1,2,,
118
+ ,4,4,,
119
+ ,,1,1,
120
+ 2,3,,,
121
+ ,,,3,2
122
+ ,,3,4,
123
+ ,5,5,,
124
+ ,,,5,3
125
+ 3,6,,,""")
126
+ ary = pd.read_csv(f).values
127
+
128
+ ret = search(ary)
129
+ print(ret)
130
+ """
131
+ [[nan nan 1. 1. nan]
132
+ [nan nan nan 2. 1.]
133
+ [nan 1. 2. nan nan]
134
+ [ 1. 2. nan nan nan]
135
+ [ 2. 3. nan nan nan]
136
+ [nan nan nan 3. 2.]
137
+ [nan nan 3. 4. nan]
138
+ [nan 4. 4. nan nan]
139
+ [nan 5. 5. nan nan]
140
+ [nan nan nan 5. 3.]
141
+ [nan nan 6. 6. nan]
142
+ [nan nan nan 7. 4.]
143
+ [nan nan 7. 8. nan]
144
+ [ 3. 6. nan nan nan]
145
+ [ 4. 7. nan nan nan]]
146
+ """
60
147
  ```