Chris@87
|
1 from __future__ import division, absolute_import, print_function
|
Chris@87
|
2
|
Chris@87
|
3 import warnings
|
Chris@87
|
4
|
Chris@87
|
5 import numpy.core.numeric as _nx
|
Chris@87
|
6 from numpy.core.numeric import (
|
Chris@87
|
7 asarray, zeros, outer, concatenate, isscalar, array, asanyarray
|
Chris@87
|
8 )
|
Chris@87
|
9 from numpy.core.fromnumeric import product, reshape
|
Chris@87
|
10 from numpy.core import vstack, atleast_3d
|
Chris@87
|
11
|
Chris@87
|
12
|
Chris@87
|
13 __all__ = [
|
Chris@87
|
14 'column_stack', 'row_stack', 'dstack', 'array_split', 'split',
|
Chris@87
|
15 'hsplit', 'vsplit', 'dsplit', 'apply_over_axes', 'expand_dims',
|
Chris@87
|
16 'apply_along_axis', 'kron', 'tile', 'get_array_wrap'
|
Chris@87
|
17 ]
|
Chris@87
|
18
|
Chris@87
|
19
|
Chris@87
|
20 def apply_along_axis(func1d, axis, arr, *args, **kwargs):
|
Chris@87
|
21 """
|
Chris@87
|
22 Apply a function to 1-D slices along the given axis.
|
Chris@87
|
23
|
Chris@87
|
24 Execute `func1d(a, *args)` where `func1d` operates on 1-D arrays and `a`
|
Chris@87
|
25 is a 1-D slice of `arr` along `axis`.
|
Chris@87
|
26
|
Chris@87
|
27 Parameters
|
Chris@87
|
28 ----------
|
Chris@87
|
29 func1d : function
|
Chris@87
|
30 This function should accept 1-D arrays. It is applied to 1-D
|
Chris@87
|
31 slices of `arr` along the specified axis.
|
Chris@87
|
32 axis : integer
|
Chris@87
|
33 Axis along which `arr` is sliced.
|
Chris@87
|
34 arr : ndarray
|
Chris@87
|
35 Input array.
|
Chris@87
|
36 args : any
|
Chris@87
|
37 Additional arguments to `func1d`.
|
Chris@87
|
38 kwargs: any
|
Chris@87
|
39 Additional named arguments to `func1d`.
|
Chris@87
|
40
|
Chris@87
|
41 .. versionadded:: 1.9.0
|
Chris@87
|
42
|
Chris@87
|
43
|
Chris@87
|
44 Returns
|
Chris@87
|
45 -------
|
Chris@87
|
46 apply_along_axis : ndarray
|
Chris@87
|
47 The output array. The shape of `outarr` is identical to the shape of
|
Chris@87
|
48 `arr`, except along the `axis` dimension, where the length of `outarr`
|
Chris@87
|
49 is equal to the size of the return value of `func1d`. If `func1d`
|
Chris@87
|
50 returns a scalar `outarr` will have one fewer dimensions than `arr`.
|
Chris@87
|
51
|
Chris@87
|
52 See Also
|
Chris@87
|
53 --------
|
Chris@87
|
54 apply_over_axes : Apply a function repeatedly over multiple axes.
|
Chris@87
|
55
|
Chris@87
|
56 Examples
|
Chris@87
|
57 --------
|
Chris@87
|
58 >>> def my_func(a):
|
Chris@87
|
59 ... \"\"\"Average first and last element of a 1-D array\"\"\"
|
Chris@87
|
60 ... return (a[0] + a[-1]) * 0.5
|
Chris@87
|
61 >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
|
Chris@87
|
62 >>> np.apply_along_axis(my_func, 0, b)
|
Chris@87
|
63 array([ 4., 5., 6.])
|
Chris@87
|
64 >>> np.apply_along_axis(my_func, 1, b)
|
Chris@87
|
65 array([ 2., 5., 8.])
|
Chris@87
|
66
|
Chris@87
|
67 For a function that doesn't return a scalar, the number of dimensions in
|
Chris@87
|
68 `outarr` is the same as `arr`.
|
Chris@87
|
69
|
Chris@87
|
70 >>> b = np.array([[8,1,7], [4,3,9], [5,2,6]])
|
Chris@87
|
71 >>> np.apply_along_axis(sorted, 1, b)
|
Chris@87
|
72 array([[1, 7, 8],
|
Chris@87
|
73 [3, 4, 9],
|
Chris@87
|
74 [2, 5, 6]])
|
Chris@87
|
75
|
Chris@87
|
76 """
|
Chris@87
|
77 arr = asarray(arr)
|
Chris@87
|
78 nd = arr.ndim
|
Chris@87
|
79 if axis < 0:
|
Chris@87
|
80 axis += nd
|
Chris@87
|
81 if (axis >= nd):
|
Chris@87
|
82 raise ValueError("axis must be less than arr.ndim; axis=%d, rank=%d."
|
Chris@87
|
83 % (axis, nd))
|
Chris@87
|
84 ind = [0]*(nd-1)
|
Chris@87
|
85 i = zeros(nd, 'O')
|
Chris@87
|
86 indlist = list(range(nd))
|
Chris@87
|
87 indlist.remove(axis)
|
Chris@87
|
88 i[axis] = slice(None, None)
|
Chris@87
|
89 outshape = asarray(arr.shape).take(indlist)
|
Chris@87
|
90 i.put(indlist, ind)
|
Chris@87
|
91 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
|
Chris@87
|
92 # if res is a number, then we have a smaller output array
|
Chris@87
|
93 if isscalar(res):
|
Chris@87
|
94 outarr = zeros(outshape, asarray(res).dtype)
|
Chris@87
|
95 outarr[tuple(ind)] = res
|
Chris@87
|
96 Ntot = product(outshape)
|
Chris@87
|
97 k = 1
|
Chris@87
|
98 while k < Ntot:
|
Chris@87
|
99 # increment the index
|
Chris@87
|
100 ind[-1] += 1
|
Chris@87
|
101 n = -1
|
Chris@87
|
102 while (ind[n] >= outshape[n]) and (n > (1-nd)):
|
Chris@87
|
103 ind[n-1] += 1
|
Chris@87
|
104 ind[n] = 0
|
Chris@87
|
105 n -= 1
|
Chris@87
|
106 i.put(indlist, ind)
|
Chris@87
|
107 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
|
Chris@87
|
108 outarr[tuple(ind)] = res
|
Chris@87
|
109 k += 1
|
Chris@87
|
110 return outarr
|
Chris@87
|
111 else:
|
Chris@87
|
112 Ntot = product(outshape)
|
Chris@87
|
113 holdshape = outshape
|
Chris@87
|
114 outshape = list(arr.shape)
|
Chris@87
|
115 outshape[axis] = len(res)
|
Chris@87
|
116 outarr = zeros(outshape, asarray(res).dtype)
|
Chris@87
|
117 outarr[tuple(i.tolist())] = res
|
Chris@87
|
118 k = 1
|
Chris@87
|
119 while k < Ntot:
|
Chris@87
|
120 # increment the index
|
Chris@87
|
121 ind[-1] += 1
|
Chris@87
|
122 n = -1
|
Chris@87
|
123 while (ind[n] >= holdshape[n]) and (n > (1-nd)):
|
Chris@87
|
124 ind[n-1] += 1
|
Chris@87
|
125 ind[n] = 0
|
Chris@87
|
126 n -= 1
|
Chris@87
|
127 i.put(indlist, ind)
|
Chris@87
|
128 res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
|
Chris@87
|
129 outarr[tuple(i.tolist())] = res
|
Chris@87
|
130 k += 1
|
Chris@87
|
131 return outarr
|
Chris@87
|
132
|
Chris@87
|
133
|
Chris@87
|
134 def apply_over_axes(func, a, axes):
|
Chris@87
|
135 """
|
Chris@87
|
136 Apply a function repeatedly over multiple axes.
|
Chris@87
|
137
|
Chris@87
|
138 `func` is called as `res = func(a, axis)`, where `axis` is the first
|
Chris@87
|
139 element of `axes`. The result `res` of the function call must have
|
Chris@87
|
140 either the same dimensions as `a` or one less dimension. If `res`
|
Chris@87
|
141 has one less dimension than `a`, a dimension is inserted before
|
Chris@87
|
142 `axis`. The call to `func` is then repeated for each axis in `axes`,
|
Chris@87
|
143 with `res` as the first argument.
|
Chris@87
|
144
|
Chris@87
|
145 Parameters
|
Chris@87
|
146 ----------
|
Chris@87
|
147 func : function
|
Chris@87
|
148 This function must take two arguments, `func(a, axis)`.
|
Chris@87
|
149 a : array_like
|
Chris@87
|
150 Input array.
|
Chris@87
|
151 axes : array_like
|
Chris@87
|
152 Axes over which `func` is applied; the elements must be integers.
|
Chris@87
|
153
|
Chris@87
|
154 Returns
|
Chris@87
|
155 -------
|
Chris@87
|
156 apply_over_axis : ndarray
|
Chris@87
|
157 The output array. The number of dimensions is the same as `a`,
|
Chris@87
|
158 but the shape can be different. This depends on whether `func`
|
Chris@87
|
159 changes the shape of its output with respect to its input.
|
Chris@87
|
160
|
Chris@87
|
161 See Also
|
Chris@87
|
162 --------
|
Chris@87
|
163 apply_along_axis :
|
Chris@87
|
164 Apply a function to 1-D slices of an array along the given axis.
|
Chris@87
|
165
|
Chris@87
|
166 Notes
|
Chris@87
|
167 ------
|
Chris@87
|
168 This function is equivalent to tuple axis arguments to reorderable ufuncs
|
Chris@87
|
169 with keepdims=True. Tuple axis arguments to ufuncs have been availabe since
|
Chris@87
|
170 version 1.7.0.
|
Chris@87
|
171
|
Chris@87
|
172 Examples
|
Chris@87
|
173 --------
|
Chris@87
|
174 >>> a = np.arange(24).reshape(2,3,4)
|
Chris@87
|
175 >>> a
|
Chris@87
|
176 array([[[ 0, 1, 2, 3],
|
Chris@87
|
177 [ 4, 5, 6, 7],
|
Chris@87
|
178 [ 8, 9, 10, 11]],
|
Chris@87
|
179 [[12, 13, 14, 15],
|
Chris@87
|
180 [16, 17, 18, 19],
|
Chris@87
|
181 [20, 21, 22, 23]]])
|
Chris@87
|
182
|
Chris@87
|
183 Sum over axes 0 and 2. The result has same number of dimensions
|
Chris@87
|
184 as the original array:
|
Chris@87
|
185
|
Chris@87
|
186 >>> np.apply_over_axes(np.sum, a, [0,2])
|
Chris@87
|
187 array([[[ 60],
|
Chris@87
|
188 [ 92],
|
Chris@87
|
189 [124]]])
|
Chris@87
|
190
|
Chris@87
|
191 Tuple axis arguments to ufuncs are equivalent:
|
Chris@87
|
192
|
Chris@87
|
193 >>> np.sum(a, axis=(0,2), keepdims=True)
|
Chris@87
|
194 array([[[ 60],
|
Chris@87
|
195 [ 92],
|
Chris@87
|
196 [124]]])
|
Chris@87
|
197
|
Chris@87
|
198 """
|
Chris@87
|
199 val = asarray(a)
|
Chris@87
|
200 N = a.ndim
|
Chris@87
|
201 if array(axes).ndim == 0:
|
Chris@87
|
202 axes = (axes,)
|
Chris@87
|
203 for axis in axes:
|
Chris@87
|
204 if axis < 0:
|
Chris@87
|
205 axis = N + axis
|
Chris@87
|
206 args = (val, axis)
|
Chris@87
|
207 res = func(*args)
|
Chris@87
|
208 if res.ndim == val.ndim:
|
Chris@87
|
209 val = res
|
Chris@87
|
210 else:
|
Chris@87
|
211 res = expand_dims(res, axis)
|
Chris@87
|
212 if res.ndim == val.ndim:
|
Chris@87
|
213 val = res
|
Chris@87
|
214 else:
|
Chris@87
|
215 raise ValueError("function is not returning "
|
Chris@87
|
216 "an array of the correct shape")
|
Chris@87
|
217 return val
|
Chris@87
|
218
|
Chris@87
|
219 def expand_dims(a, axis):
|
Chris@87
|
220 """
|
Chris@87
|
221 Expand the shape of an array.
|
Chris@87
|
222
|
Chris@87
|
223 Insert a new axis, corresponding to a given position in the array shape.
|
Chris@87
|
224
|
Chris@87
|
225 Parameters
|
Chris@87
|
226 ----------
|
Chris@87
|
227 a : array_like
|
Chris@87
|
228 Input array.
|
Chris@87
|
229 axis : int
|
Chris@87
|
230 Position (amongst axes) where new axis is to be inserted.
|
Chris@87
|
231
|
Chris@87
|
232 Returns
|
Chris@87
|
233 -------
|
Chris@87
|
234 res : ndarray
|
Chris@87
|
235 Output array. The number of dimensions is one greater than that of
|
Chris@87
|
236 the input array.
|
Chris@87
|
237
|
Chris@87
|
238 See Also
|
Chris@87
|
239 --------
|
Chris@87
|
240 doc.indexing, atleast_1d, atleast_2d, atleast_3d
|
Chris@87
|
241
|
Chris@87
|
242 Examples
|
Chris@87
|
243 --------
|
Chris@87
|
244 >>> x = np.array([1,2])
|
Chris@87
|
245 >>> x.shape
|
Chris@87
|
246 (2,)
|
Chris@87
|
247
|
Chris@87
|
248 The following is equivalent to ``x[np.newaxis,:]`` or ``x[np.newaxis]``:
|
Chris@87
|
249
|
Chris@87
|
250 >>> y = np.expand_dims(x, axis=0)
|
Chris@87
|
251 >>> y
|
Chris@87
|
252 array([[1, 2]])
|
Chris@87
|
253 >>> y.shape
|
Chris@87
|
254 (1, 2)
|
Chris@87
|
255
|
Chris@87
|
256 >>> y = np.expand_dims(x, axis=1) # Equivalent to x[:,newaxis]
|
Chris@87
|
257 >>> y
|
Chris@87
|
258 array([[1],
|
Chris@87
|
259 [2]])
|
Chris@87
|
260 >>> y.shape
|
Chris@87
|
261 (2, 1)
|
Chris@87
|
262
|
Chris@87
|
263 Note that some examples may use ``None`` instead of ``np.newaxis``. These
|
Chris@87
|
264 are the same objects:
|
Chris@87
|
265
|
Chris@87
|
266 >>> np.newaxis is None
|
Chris@87
|
267 True
|
Chris@87
|
268
|
Chris@87
|
269 """
|
Chris@87
|
270 a = asarray(a)
|
Chris@87
|
271 shape = a.shape
|
Chris@87
|
272 if axis < 0:
|
Chris@87
|
273 axis = axis + len(shape) + 1
|
Chris@87
|
274 return a.reshape(shape[:axis] + (1,) + shape[axis:])
|
Chris@87
|
275
|
Chris@87
|
276 row_stack = vstack
|
Chris@87
|
277
|
Chris@87
|
278 def column_stack(tup):
|
Chris@87
|
279 """
|
Chris@87
|
280 Stack 1-D arrays as columns into a 2-D array.
|
Chris@87
|
281
|
Chris@87
|
282 Take a sequence of 1-D arrays and stack them as columns
|
Chris@87
|
283 to make a single 2-D array. 2-D arrays are stacked as-is,
|
Chris@87
|
284 just like with `hstack`. 1-D arrays are turned into 2-D columns
|
Chris@87
|
285 first.
|
Chris@87
|
286
|
Chris@87
|
287 Parameters
|
Chris@87
|
288 ----------
|
Chris@87
|
289 tup : sequence of 1-D or 2-D arrays.
|
Chris@87
|
290 Arrays to stack. All of them must have the same first dimension.
|
Chris@87
|
291
|
Chris@87
|
292 Returns
|
Chris@87
|
293 -------
|
Chris@87
|
294 stacked : 2-D array
|
Chris@87
|
295 The array formed by stacking the given arrays.
|
Chris@87
|
296
|
Chris@87
|
297 See Also
|
Chris@87
|
298 --------
|
Chris@87
|
299 hstack, vstack, concatenate
|
Chris@87
|
300
|
Chris@87
|
301 Examples
|
Chris@87
|
302 --------
|
Chris@87
|
303 >>> a = np.array((1,2,3))
|
Chris@87
|
304 >>> b = np.array((2,3,4))
|
Chris@87
|
305 >>> np.column_stack((a,b))
|
Chris@87
|
306 array([[1, 2],
|
Chris@87
|
307 [2, 3],
|
Chris@87
|
308 [3, 4]])
|
Chris@87
|
309
|
Chris@87
|
310 """
|
Chris@87
|
311 arrays = []
|
Chris@87
|
312 for v in tup:
|
Chris@87
|
313 arr = array(v, copy=False, subok=True)
|
Chris@87
|
314 if arr.ndim < 2:
|
Chris@87
|
315 arr = array(arr, copy=False, subok=True, ndmin=2).T
|
Chris@87
|
316 arrays.append(arr)
|
Chris@87
|
317 return _nx.concatenate(arrays, 1)
|
Chris@87
|
318
|
Chris@87
|
319 def dstack(tup):
|
Chris@87
|
320 """
|
Chris@87
|
321 Stack arrays in sequence depth wise (along third axis).
|
Chris@87
|
322
|
Chris@87
|
323 Takes a sequence of arrays and stack them along the third axis
|
Chris@87
|
324 to make a single array. Rebuilds arrays divided by `dsplit`.
|
Chris@87
|
325 This is a simple way to stack 2D arrays (images) into a single
|
Chris@87
|
326 3D array for processing.
|
Chris@87
|
327
|
Chris@87
|
328 Parameters
|
Chris@87
|
329 ----------
|
Chris@87
|
330 tup : sequence of arrays
|
Chris@87
|
331 Arrays to stack. All of them must have the same shape along all
|
Chris@87
|
332 but the third axis.
|
Chris@87
|
333
|
Chris@87
|
334 Returns
|
Chris@87
|
335 -------
|
Chris@87
|
336 stacked : ndarray
|
Chris@87
|
337 The array formed by stacking the given arrays.
|
Chris@87
|
338
|
Chris@87
|
339 See Also
|
Chris@87
|
340 --------
|
Chris@87
|
341 vstack : Stack along first axis.
|
Chris@87
|
342 hstack : Stack along second axis.
|
Chris@87
|
343 concatenate : Join arrays.
|
Chris@87
|
344 dsplit : Split array along third axis.
|
Chris@87
|
345
|
Chris@87
|
346 Notes
|
Chris@87
|
347 -----
|
Chris@87
|
348 Equivalent to ``np.concatenate(tup, axis=2)``.
|
Chris@87
|
349
|
Chris@87
|
350 Examples
|
Chris@87
|
351 --------
|
Chris@87
|
352 >>> a = np.array((1,2,3))
|
Chris@87
|
353 >>> b = np.array((2,3,4))
|
Chris@87
|
354 >>> np.dstack((a,b))
|
Chris@87
|
355 array([[[1, 2],
|
Chris@87
|
356 [2, 3],
|
Chris@87
|
357 [3, 4]]])
|
Chris@87
|
358
|
Chris@87
|
359 >>> a = np.array([[1],[2],[3]])
|
Chris@87
|
360 >>> b = np.array([[2],[3],[4]])
|
Chris@87
|
361 >>> np.dstack((a,b))
|
Chris@87
|
362 array([[[1, 2]],
|
Chris@87
|
363 [[2, 3]],
|
Chris@87
|
364 [[3, 4]]])
|
Chris@87
|
365
|
Chris@87
|
366 """
|
Chris@87
|
367 return _nx.concatenate([atleast_3d(_m) for _m in tup], 2)
|
Chris@87
|
368
|
Chris@87
|
369 def _replace_zero_by_x_arrays(sub_arys):
|
Chris@87
|
370 for i in range(len(sub_arys)):
|
Chris@87
|
371 if len(_nx.shape(sub_arys[i])) == 0:
|
Chris@87
|
372 sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
|
Chris@87
|
373 elif _nx.sometrue(_nx.equal(_nx.shape(sub_arys[i]), 0)):
|
Chris@87
|
374 sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
|
Chris@87
|
375 return sub_arys
|
Chris@87
|
376
|
Chris@87
|
377 def array_split(ary, indices_or_sections, axis=0):
|
Chris@87
|
378 """
|
Chris@87
|
379 Split an array into multiple sub-arrays.
|
Chris@87
|
380
|
Chris@87
|
381 Please refer to the ``split`` documentation. The only difference
|
Chris@87
|
382 between these functions is that ``array_split`` allows
|
Chris@87
|
383 `indices_or_sections` to be an integer that does *not* equally
|
Chris@87
|
384 divide the axis.
|
Chris@87
|
385
|
Chris@87
|
386 See Also
|
Chris@87
|
387 --------
|
Chris@87
|
388 split : Split array into multiple sub-arrays of equal size.
|
Chris@87
|
389
|
Chris@87
|
390 Examples
|
Chris@87
|
391 --------
|
Chris@87
|
392 >>> x = np.arange(8.0)
|
Chris@87
|
393 >>> np.array_split(x, 3)
|
Chris@87
|
394 [array([ 0., 1., 2.]), array([ 3., 4., 5.]), array([ 6., 7.])]
|
Chris@87
|
395
|
Chris@87
|
396 """
|
Chris@87
|
397 try:
|
Chris@87
|
398 Ntotal = ary.shape[axis]
|
Chris@87
|
399 except AttributeError:
|
Chris@87
|
400 Ntotal = len(ary)
|
Chris@87
|
401 try:
|
Chris@87
|
402 # handle scalar case.
|
Chris@87
|
403 Nsections = len(indices_or_sections) + 1
|
Chris@87
|
404 div_points = [0] + list(indices_or_sections) + [Ntotal]
|
Chris@87
|
405 except TypeError:
|
Chris@87
|
406 # indices_or_sections is a scalar, not an array.
|
Chris@87
|
407 Nsections = int(indices_or_sections)
|
Chris@87
|
408 if Nsections <= 0:
|
Chris@87
|
409 raise ValueError('number sections must be larger than 0.')
|
Chris@87
|
410 Neach_section, extras = divmod(Ntotal, Nsections)
|
Chris@87
|
411 section_sizes = ([0] +
|
Chris@87
|
412 extras * [Neach_section+1] +
|
Chris@87
|
413 (Nsections-extras) * [Neach_section])
|
Chris@87
|
414 div_points = _nx.array(section_sizes).cumsum()
|
Chris@87
|
415
|
Chris@87
|
416 sub_arys = []
|
Chris@87
|
417 sary = _nx.swapaxes(ary, axis, 0)
|
Chris@87
|
418 for i in range(Nsections):
|
Chris@87
|
419 st = div_points[i]
|
Chris@87
|
420 end = div_points[i + 1]
|
Chris@87
|
421 sub_arys.append(_nx.swapaxes(sary[st:end], axis, 0))
|
Chris@87
|
422
|
Chris@87
|
423 # This "kludge" was introduced here to replace arrays shaped (0, 10)
|
Chris@87
|
424 # or similar with an array shaped (0,).
|
Chris@87
|
425 # There seems no need for this, so give a FutureWarning to remove later.
|
Chris@87
|
426 if sub_arys[-1].size == 0 and sub_arys[-1].ndim != 1:
|
Chris@87
|
427 warnings.warn("in the future np.array_split will retain the shape of "
|
Chris@87
|
428 "arrays with a zero size, instead of replacing them by "
|
Chris@87
|
429 "`array([])`, which always has a shape of (0,).",
|
Chris@87
|
430 FutureWarning)
|
Chris@87
|
431 sub_arys = _replace_zero_by_x_arrays(sub_arys)
|
Chris@87
|
432
|
Chris@87
|
433 return sub_arys
|
Chris@87
|
434
|
Chris@87
|
435 def split(ary,indices_or_sections,axis=0):
|
Chris@87
|
436 """
|
Chris@87
|
437 Split an array into multiple sub-arrays.
|
Chris@87
|
438
|
Chris@87
|
439 Parameters
|
Chris@87
|
440 ----------
|
Chris@87
|
441 ary : ndarray
|
Chris@87
|
442 Array to be divided into sub-arrays.
|
Chris@87
|
443 indices_or_sections : int or 1-D array
|
Chris@87
|
444 If `indices_or_sections` is an integer, N, the array will be divided
|
Chris@87
|
445 into N equal arrays along `axis`. If such a split is not possible,
|
Chris@87
|
446 an error is raised.
|
Chris@87
|
447
|
Chris@87
|
448 If `indices_or_sections` is a 1-D array of sorted integers, the entries
|
Chris@87
|
449 indicate where along `axis` the array is split. For example,
|
Chris@87
|
450 ``[2, 3]`` would, for ``axis=0``, result in
|
Chris@87
|
451
|
Chris@87
|
452 - ary[:2]
|
Chris@87
|
453 - ary[2:3]
|
Chris@87
|
454 - ary[3:]
|
Chris@87
|
455
|
Chris@87
|
456 If an index exceeds the dimension of the array along `axis`,
|
Chris@87
|
457 an empty sub-array is returned correspondingly.
|
Chris@87
|
458 axis : int, optional
|
Chris@87
|
459 The axis along which to split, default is 0.
|
Chris@87
|
460
|
Chris@87
|
461 Returns
|
Chris@87
|
462 -------
|
Chris@87
|
463 sub-arrays : list of ndarrays
|
Chris@87
|
464 A list of sub-arrays.
|
Chris@87
|
465
|
Chris@87
|
466 Raises
|
Chris@87
|
467 ------
|
Chris@87
|
468 ValueError
|
Chris@87
|
469 If `indices_or_sections` is given as an integer, but
|
Chris@87
|
470 a split does not result in equal division.
|
Chris@87
|
471
|
Chris@87
|
472 See Also
|
Chris@87
|
473 --------
|
Chris@87
|
474 array_split : Split an array into multiple sub-arrays of equal or
|
Chris@87
|
475 near-equal size. Does not raise an exception if
|
Chris@87
|
476 an equal division cannot be made.
|
Chris@87
|
477 hsplit : Split array into multiple sub-arrays horizontally (column-wise).
|
Chris@87
|
478 vsplit : Split array into multiple sub-arrays vertically (row wise).
|
Chris@87
|
479 dsplit : Split array into multiple sub-arrays along the 3rd axis (depth).
|
Chris@87
|
480 concatenate : Join arrays together.
|
Chris@87
|
481 hstack : Stack arrays in sequence horizontally (column wise).
|
Chris@87
|
482 vstack : Stack arrays in sequence vertically (row wise).
|
Chris@87
|
483 dstack : Stack arrays in sequence depth wise (along third dimension).
|
Chris@87
|
484
|
Chris@87
|
485 Examples
|
Chris@87
|
486 --------
|
Chris@87
|
487 >>> x = np.arange(9.0)
|
Chris@87
|
488 >>> np.split(x, 3)
|
Chris@87
|
489 [array([ 0., 1., 2.]), array([ 3., 4., 5.]), array([ 6., 7., 8.])]
|
Chris@87
|
490
|
Chris@87
|
491 >>> x = np.arange(8.0)
|
Chris@87
|
492 >>> np.split(x, [3, 5, 6, 10])
|
Chris@87
|
493 [array([ 0., 1., 2.]),
|
Chris@87
|
494 array([ 3., 4.]),
|
Chris@87
|
495 array([ 5.]),
|
Chris@87
|
496 array([ 6., 7.]),
|
Chris@87
|
497 array([], dtype=float64)]
|
Chris@87
|
498
|
Chris@87
|
499 """
|
Chris@87
|
500 try:
|
Chris@87
|
501 len(indices_or_sections)
|
Chris@87
|
502 except TypeError:
|
Chris@87
|
503 sections = indices_or_sections
|
Chris@87
|
504 N = ary.shape[axis]
|
Chris@87
|
505 if N % sections:
|
Chris@87
|
506 raise ValueError(
|
Chris@87
|
507 'array split does not result in an equal division')
|
Chris@87
|
508 res = array_split(ary, indices_or_sections, axis)
|
Chris@87
|
509 return res
|
Chris@87
|
510
|
Chris@87
|
511 def hsplit(ary, indices_or_sections):
|
Chris@87
|
512 """
|
Chris@87
|
513 Split an array into multiple sub-arrays horizontally (column-wise).
|
Chris@87
|
514
|
Chris@87
|
515 Please refer to the `split` documentation. `hsplit` is equivalent
|
Chris@87
|
516 to `split` with ``axis=1``, the array is always split along the second
|
Chris@87
|
517 axis regardless of the array dimension.
|
Chris@87
|
518
|
Chris@87
|
519 See Also
|
Chris@87
|
520 --------
|
Chris@87
|
521 split : Split an array into multiple sub-arrays of equal size.
|
Chris@87
|
522
|
Chris@87
|
523 Examples
|
Chris@87
|
524 --------
|
Chris@87
|
525 >>> x = np.arange(16.0).reshape(4, 4)
|
Chris@87
|
526 >>> x
|
Chris@87
|
527 array([[ 0., 1., 2., 3.],
|
Chris@87
|
528 [ 4., 5., 6., 7.],
|
Chris@87
|
529 [ 8., 9., 10., 11.],
|
Chris@87
|
530 [ 12., 13., 14., 15.]])
|
Chris@87
|
531 >>> np.hsplit(x, 2)
|
Chris@87
|
532 [array([[ 0., 1.],
|
Chris@87
|
533 [ 4., 5.],
|
Chris@87
|
534 [ 8., 9.],
|
Chris@87
|
535 [ 12., 13.]]),
|
Chris@87
|
536 array([[ 2., 3.],
|
Chris@87
|
537 [ 6., 7.],
|
Chris@87
|
538 [ 10., 11.],
|
Chris@87
|
539 [ 14., 15.]])]
|
Chris@87
|
540 >>> np.hsplit(x, np.array([3, 6]))
|
Chris@87
|
541 [array([[ 0., 1., 2.],
|
Chris@87
|
542 [ 4., 5., 6.],
|
Chris@87
|
543 [ 8., 9., 10.],
|
Chris@87
|
544 [ 12., 13., 14.]]),
|
Chris@87
|
545 array([[ 3.],
|
Chris@87
|
546 [ 7.],
|
Chris@87
|
547 [ 11.],
|
Chris@87
|
548 [ 15.]]),
|
Chris@87
|
549 array([], dtype=float64)]
|
Chris@87
|
550
|
Chris@87
|
551 With a higher dimensional array the split is still along the second axis.
|
Chris@87
|
552
|
Chris@87
|
553 >>> x = np.arange(8.0).reshape(2, 2, 2)
|
Chris@87
|
554 >>> x
|
Chris@87
|
555 array([[[ 0., 1.],
|
Chris@87
|
556 [ 2., 3.]],
|
Chris@87
|
557 [[ 4., 5.],
|
Chris@87
|
558 [ 6., 7.]]])
|
Chris@87
|
559 >>> np.hsplit(x, 2)
|
Chris@87
|
560 [array([[[ 0., 1.]],
|
Chris@87
|
561 [[ 4., 5.]]]),
|
Chris@87
|
562 array([[[ 2., 3.]],
|
Chris@87
|
563 [[ 6., 7.]]])]
|
Chris@87
|
564
|
Chris@87
|
565 """
|
Chris@87
|
566 if len(_nx.shape(ary)) == 0:
|
Chris@87
|
567 raise ValueError('hsplit only works on arrays of 1 or more dimensions')
|
Chris@87
|
568 if len(ary.shape) > 1:
|
Chris@87
|
569 return split(ary, indices_or_sections, 1)
|
Chris@87
|
570 else:
|
Chris@87
|
571 return split(ary, indices_or_sections, 0)
|
Chris@87
|
572
|
Chris@87
|
573 def vsplit(ary, indices_or_sections):
|
Chris@87
|
574 """
|
Chris@87
|
575 Split an array into multiple sub-arrays vertically (row-wise).
|
Chris@87
|
576
|
Chris@87
|
577 Please refer to the ``split`` documentation. ``vsplit`` is equivalent
|
Chris@87
|
578 to ``split`` with `axis=0` (default), the array is always split along the
|
Chris@87
|
579 first axis regardless of the array dimension.
|
Chris@87
|
580
|
Chris@87
|
581 See Also
|
Chris@87
|
582 --------
|
Chris@87
|
583 split : Split an array into multiple sub-arrays of equal size.
|
Chris@87
|
584
|
Chris@87
|
585 Examples
|
Chris@87
|
586 --------
|
Chris@87
|
587 >>> x = np.arange(16.0).reshape(4, 4)
|
Chris@87
|
588 >>> x
|
Chris@87
|
589 array([[ 0., 1., 2., 3.],
|
Chris@87
|
590 [ 4., 5., 6., 7.],
|
Chris@87
|
591 [ 8., 9., 10., 11.],
|
Chris@87
|
592 [ 12., 13., 14., 15.]])
|
Chris@87
|
593 >>> np.vsplit(x, 2)
|
Chris@87
|
594 [array([[ 0., 1., 2., 3.],
|
Chris@87
|
595 [ 4., 5., 6., 7.]]),
|
Chris@87
|
596 array([[ 8., 9., 10., 11.],
|
Chris@87
|
597 [ 12., 13., 14., 15.]])]
|
Chris@87
|
598 >>> np.vsplit(x, np.array([3, 6]))
|
Chris@87
|
599 [array([[ 0., 1., 2., 3.],
|
Chris@87
|
600 [ 4., 5., 6., 7.],
|
Chris@87
|
601 [ 8., 9., 10., 11.]]),
|
Chris@87
|
602 array([[ 12., 13., 14., 15.]]),
|
Chris@87
|
603 array([], dtype=float64)]
|
Chris@87
|
604
|
Chris@87
|
605 With a higher dimensional array the split is still along the first axis.
|
Chris@87
|
606
|
Chris@87
|
607 >>> x = np.arange(8.0).reshape(2, 2, 2)
|
Chris@87
|
608 >>> x
|
Chris@87
|
609 array([[[ 0., 1.],
|
Chris@87
|
610 [ 2., 3.]],
|
Chris@87
|
611 [[ 4., 5.],
|
Chris@87
|
612 [ 6., 7.]]])
|
Chris@87
|
613 >>> np.vsplit(x, 2)
|
Chris@87
|
614 [array([[[ 0., 1.],
|
Chris@87
|
615 [ 2., 3.]]]),
|
Chris@87
|
616 array([[[ 4., 5.],
|
Chris@87
|
617 [ 6., 7.]]])]
|
Chris@87
|
618
|
Chris@87
|
619 """
|
Chris@87
|
620 if len(_nx.shape(ary)) < 2:
|
Chris@87
|
621 raise ValueError('vsplit only works on arrays of 2 or more dimensions')
|
Chris@87
|
622 return split(ary, indices_or_sections, 0)
|
Chris@87
|
623
|
Chris@87
|
624 def dsplit(ary, indices_or_sections):
|
Chris@87
|
625 """
|
Chris@87
|
626 Split array into multiple sub-arrays along the 3rd axis (depth).
|
Chris@87
|
627
|
Chris@87
|
628 Please refer to the `split` documentation. `dsplit` is equivalent
|
Chris@87
|
629 to `split` with ``axis=2``, the array is always split along the third
|
Chris@87
|
630 axis provided the array dimension is greater than or equal to 3.
|
Chris@87
|
631
|
Chris@87
|
632 See Also
|
Chris@87
|
633 --------
|
Chris@87
|
634 split : Split an array into multiple sub-arrays of equal size.
|
Chris@87
|
635
|
Chris@87
|
636 Examples
|
Chris@87
|
637 --------
|
Chris@87
|
638 >>> x = np.arange(16.0).reshape(2, 2, 4)
|
Chris@87
|
639 >>> x
|
Chris@87
|
640 array([[[ 0., 1., 2., 3.],
|
Chris@87
|
641 [ 4., 5., 6., 7.]],
|
Chris@87
|
642 [[ 8., 9., 10., 11.],
|
Chris@87
|
643 [ 12., 13., 14., 15.]]])
|
Chris@87
|
644 >>> np.dsplit(x, 2)
|
Chris@87
|
645 [array([[[ 0., 1.],
|
Chris@87
|
646 [ 4., 5.]],
|
Chris@87
|
647 [[ 8., 9.],
|
Chris@87
|
648 [ 12., 13.]]]),
|
Chris@87
|
649 array([[[ 2., 3.],
|
Chris@87
|
650 [ 6., 7.]],
|
Chris@87
|
651 [[ 10., 11.],
|
Chris@87
|
652 [ 14., 15.]]])]
|
Chris@87
|
653 >>> np.dsplit(x, np.array([3, 6]))
|
Chris@87
|
654 [array([[[ 0., 1., 2.],
|
Chris@87
|
655 [ 4., 5., 6.]],
|
Chris@87
|
656 [[ 8., 9., 10.],
|
Chris@87
|
657 [ 12., 13., 14.]]]),
|
Chris@87
|
658 array([[[ 3.],
|
Chris@87
|
659 [ 7.]],
|
Chris@87
|
660 [[ 11.],
|
Chris@87
|
661 [ 15.]]]),
|
Chris@87
|
662 array([], dtype=float64)]
|
Chris@87
|
663
|
Chris@87
|
664 """
|
Chris@87
|
665 if len(_nx.shape(ary)) < 3:
|
Chris@87
|
666 raise ValueError('dsplit only works on arrays of 3 or more dimensions')
|
Chris@87
|
667 return split(ary, indices_or_sections, 2)
|
Chris@87
|
668
|
Chris@87
|
669 def get_array_prepare(*args):
|
Chris@87
|
670 """Find the wrapper for the array with the highest priority.
|
Chris@87
|
671
|
Chris@87
|
672 In case of ties, leftmost wins. If no wrapper is found, return None
|
Chris@87
|
673 """
|
Chris@87
|
674 wrappers = sorted((getattr(x, '__array_priority__', 0), -i,
|
Chris@87
|
675 x.__array_prepare__) for i, x in enumerate(args)
|
Chris@87
|
676 if hasattr(x, '__array_prepare__'))
|
Chris@87
|
677 if wrappers:
|
Chris@87
|
678 return wrappers[-1][-1]
|
Chris@87
|
679 return None
|
Chris@87
|
680
|
Chris@87
|
681 def get_array_wrap(*args):
|
Chris@87
|
682 """Find the wrapper for the array with the highest priority.
|
Chris@87
|
683
|
Chris@87
|
684 In case of ties, leftmost wins. If no wrapper is found, return None
|
Chris@87
|
685 """
|
Chris@87
|
686 wrappers = sorted((getattr(x, '__array_priority__', 0), -i,
|
Chris@87
|
687 x.__array_wrap__) for i, x in enumerate(args)
|
Chris@87
|
688 if hasattr(x, '__array_wrap__'))
|
Chris@87
|
689 if wrappers:
|
Chris@87
|
690 return wrappers[-1][-1]
|
Chris@87
|
691 return None
|
Chris@87
|
692
|
Chris@87
|
693 def kron(a, b):
|
Chris@87
|
694 """
|
Chris@87
|
695 Kronecker product of two arrays.
|
Chris@87
|
696
|
Chris@87
|
697 Computes the Kronecker product, a composite array made of blocks of the
|
Chris@87
|
698 second array scaled by the first.
|
Chris@87
|
699
|
Chris@87
|
700 Parameters
|
Chris@87
|
701 ----------
|
Chris@87
|
702 a, b : array_like
|
Chris@87
|
703
|
Chris@87
|
704 Returns
|
Chris@87
|
705 -------
|
Chris@87
|
706 out : ndarray
|
Chris@87
|
707
|
Chris@87
|
708 See Also
|
Chris@87
|
709 --------
|
Chris@87
|
710 outer : The outer product
|
Chris@87
|
711
|
Chris@87
|
712 Notes
|
Chris@87
|
713 -----
|
Chris@87
|
714 The function assumes that the number of dimenensions of `a` and `b`
|
Chris@87
|
715 are the same, if necessary prepending the smallest with ones.
|
Chris@87
|
716 If `a.shape = (r0,r1,..,rN)` and `b.shape = (s0,s1,...,sN)`,
|
Chris@87
|
717 the Kronecker product has shape `(r0*s0, r1*s1, ..., rN*SN)`.
|
Chris@87
|
718 The elements are products of elements from `a` and `b`, organized
|
Chris@87
|
719 explicitly by::
|
Chris@87
|
720
|
Chris@87
|
721 kron(a,b)[k0,k1,...,kN] = a[i0,i1,...,iN] * b[j0,j1,...,jN]
|
Chris@87
|
722
|
Chris@87
|
723 where::
|
Chris@87
|
724
|
Chris@87
|
725 kt = it * st + jt, t = 0,...,N
|
Chris@87
|
726
|
Chris@87
|
727 In the common 2-D case (N=1), the block structure can be visualized::
|
Chris@87
|
728
|
Chris@87
|
729 [[ a[0,0]*b, a[0,1]*b, ... , a[0,-1]*b ],
|
Chris@87
|
730 [ ... ... ],
|
Chris@87
|
731 [ a[-1,0]*b, a[-1,1]*b, ... , a[-1,-1]*b ]]
|
Chris@87
|
732
|
Chris@87
|
733
|
Chris@87
|
734 Examples
|
Chris@87
|
735 --------
|
Chris@87
|
736 >>> np.kron([1,10,100], [5,6,7])
|
Chris@87
|
737 array([ 5, 6, 7, 50, 60, 70, 500, 600, 700])
|
Chris@87
|
738 >>> np.kron([5,6,7], [1,10,100])
|
Chris@87
|
739 array([ 5, 50, 500, 6, 60, 600, 7, 70, 700])
|
Chris@87
|
740
|
Chris@87
|
741 >>> np.kron(np.eye(2), np.ones((2,2)))
|
Chris@87
|
742 array([[ 1., 1., 0., 0.],
|
Chris@87
|
743 [ 1., 1., 0., 0.],
|
Chris@87
|
744 [ 0., 0., 1., 1.],
|
Chris@87
|
745 [ 0., 0., 1., 1.]])
|
Chris@87
|
746
|
Chris@87
|
747 >>> a = np.arange(100).reshape((2,5,2,5))
|
Chris@87
|
748 >>> b = np.arange(24).reshape((2,3,4))
|
Chris@87
|
749 >>> c = np.kron(a,b)
|
Chris@87
|
750 >>> c.shape
|
Chris@87
|
751 (2, 10, 6, 20)
|
Chris@87
|
752 >>> I = (1,3,0,2)
|
Chris@87
|
753 >>> J = (0,2,1)
|
Chris@87
|
754 >>> J1 = (0,) + J # extend to ndim=4
|
Chris@87
|
755 >>> S1 = (1,) + b.shape
|
Chris@87
|
756 >>> K = tuple(np.array(I) * np.array(S1) + np.array(J1))
|
Chris@87
|
757 >>> c[K] == a[I]*b[J]
|
Chris@87
|
758 True
|
Chris@87
|
759
|
Chris@87
|
760 """
|
Chris@87
|
761 b = asanyarray(b)
|
Chris@87
|
762 a = array(a, copy=False, subok=True, ndmin=b.ndim)
|
Chris@87
|
763 ndb, nda = b.ndim, a.ndim
|
Chris@87
|
764 if (nda == 0 or ndb == 0):
|
Chris@87
|
765 return _nx.multiply(a, b)
|
Chris@87
|
766 as_ = a.shape
|
Chris@87
|
767 bs = b.shape
|
Chris@87
|
768 if not a.flags.contiguous:
|
Chris@87
|
769 a = reshape(a, as_)
|
Chris@87
|
770 if not b.flags.contiguous:
|
Chris@87
|
771 b = reshape(b, bs)
|
Chris@87
|
772 nd = ndb
|
Chris@87
|
773 if (ndb != nda):
|
Chris@87
|
774 if (ndb > nda):
|
Chris@87
|
775 as_ = (1,)*(ndb-nda) + as_
|
Chris@87
|
776 else:
|
Chris@87
|
777 bs = (1,)*(nda-ndb) + bs
|
Chris@87
|
778 nd = nda
|
Chris@87
|
779 result = outer(a, b).reshape(as_+bs)
|
Chris@87
|
780 axis = nd-1
|
Chris@87
|
781 for _ in range(nd):
|
Chris@87
|
782 result = concatenate(result, axis=axis)
|
Chris@87
|
783 wrapper = get_array_prepare(a, b)
|
Chris@87
|
784 if wrapper is not None:
|
Chris@87
|
785 result = wrapper(result)
|
Chris@87
|
786 wrapper = get_array_wrap(a, b)
|
Chris@87
|
787 if wrapper is not None:
|
Chris@87
|
788 result = wrapper(result)
|
Chris@87
|
789 return result
|
Chris@87
|
790
|
Chris@87
|
791
|
Chris@87
|
792 def tile(A, reps):
|
Chris@87
|
793 """
|
Chris@87
|
794 Construct an array by repeating A the number of times given by reps.
|
Chris@87
|
795
|
Chris@87
|
796 If `reps` has length ``d``, the result will have dimension of
|
Chris@87
|
797 ``max(d, A.ndim)``.
|
Chris@87
|
798
|
Chris@87
|
799 If ``A.ndim < d``, `A` is promoted to be d-dimensional by prepending new
|
Chris@87
|
800 axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication,
|
Chris@87
|
801 or shape (1, 1, 3) for 3-D replication. If this is not the desired
|
Chris@87
|
802 behavior, promote `A` to d-dimensions manually before calling this
|
Chris@87
|
803 function.
|
Chris@87
|
804
|
Chris@87
|
805 If ``A.ndim > d``, `reps` is promoted to `A`.ndim by pre-pending 1's to it.
|
Chris@87
|
806 Thus for an `A` of shape (2, 3, 4, 5), a `reps` of (2, 2) is treated as
|
Chris@87
|
807 (1, 1, 2, 2).
|
Chris@87
|
808
|
Chris@87
|
809 Parameters
|
Chris@87
|
810 ----------
|
Chris@87
|
811 A : array_like
|
Chris@87
|
812 The input array.
|
Chris@87
|
813 reps : array_like
|
Chris@87
|
814 The number of repetitions of `A` along each axis.
|
Chris@87
|
815
|
Chris@87
|
816 Returns
|
Chris@87
|
817 -------
|
Chris@87
|
818 c : ndarray
|
Chris@87
|
819 The tiled output array.
|
Chris@87
|
820
|
Chris@87
|
821 See Also
|
Chris@87
|
822 --------
|
Chris@87
|
823 repeat : Repeat elements of an array.
|
Chris@87
|
824
|
Chris@87
|
825 Examples
|
Chris@87
|
826 --------
|
Chris@87
|
827 >>> a = np.array([0, 1, 2])
|
Chris@87
|
828 >>> np.tile(a, 2)
|
Chris@87
|
829 array([0, 1, 2, 0, 1, 2])
|
Chris@87
|
830 >>> np.tile(a, (2, 2))
|
Chris@87
|
831 array([[0, 1, 2, 0, 1, 2],
|
Chris@87
|
832 [0, 1, 2, 0, 1, 2]])
|
Chris@87
|
833 >>> np.tile(a, (2, 1, 2))
|
Chris@87
|
834 array([[[0, 1, 2, 0, 1, 2]],
|
Chris@87
|
835 [[0, 1, 2, 0, 1, 2]]])
|
Chris@87
|
836
|
Chris@87
|
837 >>> b = np.array([[1, 2], [3, 4]])
|
Chris@87
|
838 >>> np.tile(b, 2)
|
Chris@87
|
839 array([[1, 2, 1, 2],
|
Chris@87
|
840 [3, 4, 3, 4]])
|
Chris@87
|
841 >>> np.tile(b, (2, 1))
|
Chris@87
|
842 array([[1, 2],
|
Chris@87
|
843 [3, 4],
|
Chris@87
|
844 [1, 2],
|
Chris@87
|
845 [3, 4]])
|
Chris@87
|
846
|
Chris@87
|
847 """
|
Chris@87
|
848 try:
|
Chris@87
|
849 tup = tuple(reps)
|
Chris@87
|
850 except TypeError:
|
Chris@87
|
851 tup = (reps,)
|
Chris@87
|
852 d = len(tup)
|
Chris@87
|
853 c = _nx.array(A, copy=False, subok=True, ndmin=d)
|
Chris@87
|
854 shape = list(c.shape)
|
Chris@87
|
855 n = max(c.size, 1)
|
Chris@87
|
856 if (d < c.ndim):
|
Chris@87
|
857 tup = (1,)*(c.ndim-d) + tup
|
Chris@87
|
858 for i, nrep in enumerate(tup):
|
Chris@87
|
859 if nrep != 1:
|
Chris@87
|
860 c = c.reshape(-1, n).repeat(nrep, 0)
|
Chris@87
|
861 dim_in = shape[i]
|
Chris@87
|
862 dim_out = dim_in*nrep
|
Chris@87
|
863 shape[i] = dim_out
|
Chris@87
|
864 n //= max(dim_in, 1)
|
Chris@87
|
865 return c.reshape(shape)
|