Why does numpy documentation recommend to prefer concatente over hstack?
but you should prefer np.concatenate or np.stack.
According to this answer hstack is a wrapper around concatenate. In that case why not use hstack which improves the readability of the code?
So the actual code in hstack is:
arrs = [atleast_1d(_m) for _m in tup]
# As a special case, dimension 0 of 1-dimensional arrays is "horizontal"
if arrs[0].ndim == 1:
return _nx.concatenate(arrs, 0)
else:
return _nx.concatenate(arrs, 1)
It first loops through the arguments and makes sure that each is at least 1d. This takes care of the 0d and scalar elements, such as in np.hstack([0,1,np.arange(3)]).
The rest chooses between concatenating on the one and only axis or the 2nd one.
vstack is similar, except it makes things atleast 2d, and concatenates on the 1st.
Judging from SO questions/answers these are still being used quite a bit, and I think in most cases they don't cause problems. It's np.append that creates most problems. That's the one I wish they'd never added.
I think the main problem with hstack and vstack is that they encourage (or at least allow) lazy thinking about dimensions and shapes. When questions arise it's because the poster doesn't understand what is means to have the same number of dimensions, or that shapes must be equal (except for one axis).
Related
Many functions like in1d and setdiff1d are designed for 1-d array. One workaround to apply these methods on N-dimensional arrays is to make numpy to treat each row (something more high dimensional) as a value.
One approach I found to do so is in this answer Get intersecting rows across two 2D numpy arrays by Joe Kington.
The following code is taken from this answer. The task Joe Kington faced was to detect common rows in two arrays A and B while trying to use in1d.
import numpy as np
A = np.array([[1,4],[2,5],[3,6]])
B = np.array([[1,4],[3,6],[7,8]])
nrows, ncols = A.shape
dtype={'names':['f{}'.format(i) for i in range(ncols)],
'formats':ncols * [A.dtype]}
C = np.intersect1d(A.view(dtype), B.view(dtype))
# This last bit is optional if you're okay with "C" being a structured array...
C = C.view(A.dtype).reshape(-1, ncols)
I am hoping you to help me with any of the following three questions. First, I do not understand the mechanisms behind this method. Can you try to explain it to me?
Second, is there other ways to let numpy treat an subarray as one object?
One more open question: dose Joe's approach have any drawbacks? I mean whether treating rows as a value might cause some problems? Sorry this question is pretty broad.
Try to post what I have learned. The method Joe used is called structured arrays. It will allow users to define what is contained in a single cell/element.
We take a look at the description of the first example the documentation provided.
x = np.array([(1,2.,'Hello'), (2,3.,"World")], ...
dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'S10')])
Here we have created a one-dimensional array of length 2. Each element
of this array is a structure that contains three items, a 32-bit
integer, a 32-bit float, and a string of length 10 or less.
Without passing in dtype, however, we will get a 2 by 3 matrix.
With this method, we would be able to let numpy treat a higher dimensional array as an single element with properly set dtype.
Another trick Joe showed is that we don't need to really form a new numpy array to achieve the purpose. We can use the view function (See ndarray.view) to change the way numpy view data. There is a section of Note section in ndarray.view that I think you should take a look before utilizing the method. I have no guarantee that there would not be side effects. The paragraph below is from the note section and seems to call for caution.
For a.view(some_dtype), if some_dtype has a different number of bytes per entry than the previous dtype (for example, converting a regular array to a structured array), then the behavior of the view cannot be predicted just from the superficial appearance of a (shown by print(a)). It also depends on exactly how a is stored in memory. Therefore if a is C-ordered versus fortran-ordered, versus defined as a slice or transpose, etc., the view may give different results.
Other reference
https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.dtypes.html
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.dtype.html
Let's assume I have an array of phases (from complex numbers)
A = np.angle(np.random.uniform(-1,1,[10,10,10]) + 1j*np.random.uniform(-1,1,[10,10,10]))
I would now like to unwrap this array in ALL dimensions. In the above 3D case I would do
A_unwrapped = np.unwrap(np.unwrap(np.unwrap(A,axis=0), axis=1),axis=2)
While this is still feasible in the 3D case, in case of higher dimensionality, this approach seems a little cumbersome to me. Is there a more efficient way to do this with numpy?
You could use np.apply_over_axes, which is supposed to apply a function over each dimension of an array in turn:
np.apply_over_axes(np.unwrap, A, np.arange(len(A.shape)))
I believe this should do it.
I'm not sure if there is a way to bypass performing the unwrap operation along each axis. Obviously if it acted on individual elements you could use vectorization, but that doesn't seem to be an option here. What you can do that will at least make the code cleaner is create a loop over the dimensions:
for dim in range(len(A.shape)):
A = np.unwrap(A, axis=dim)
You could also repeatedly apply a function that takes the dimension on which to operate as a parameter:
reduce(lambda A, axis: np.unwrap(A, axis=axis), range(len(A.shape)), A)
Remember that in Python 3 reduce needs to be imported from functools.
I'm using Numpy 1.12.1.
According to the documentation for vstack
This function continues to be supported for backward compatibility, but you should prefer np.concatenate or np.stack. The np.stack function was added in NumPy 1.10.
But there is no numpy.ma.stack function. The np.stack function does not function correctly when trying to stack masked arrays.
Should I continue using numpy.ma.vstack or is there another way to achieve the same functionality without relying on a seemingly deprecated function?
I think that deprecation statement overstates the usefulness of stack. No one is going to stop using vstack or hstack. But these are all front ends of concatenate. I encourage everyone to look at the source code for these functions to see how they manipulate dimensions prior to using `concatenate.
I see stack as more of a generalization of np.array. When given a list of 2d arrays, np.array joins them on a new axis at the front, producing a 3d array. np.stack lets you join them on 2 other new axes.
np.stack can replace vstack when given a list of 1d arrays. but not if given a mix of 1 and 2d.
Masked arrays at a bit of backwater, and don't get new features as quickly. Use the functions it provides, and don't worry about the stack docs.
ma.vstack does (where `func= np.vstack):
_d = func(tuple([np.asarray(a) for a in x]), *args, **params)
_m = func(tuple([getmaskarray(a) for a in x]), *args, **params)
return masked_array(_d, mask=_m)
It does a vstack on the .data and mask parts, and then creates a new masked array. Looks like it could easily be extended to work with np.stack.
a python question: I've got a np.einsum operation that I'm doing on a pair of 3d arrays:
return np.einsum('ijk, ijk -> ik', input_array, self._beta_array)
Problem I'm having is the result is 2d; the operation collapses the 'j' dimension. What I'd love to do is to have it retain the 'j' dimension similar to how 'keepdims' works in the np.sum function.
I can wrap the result in np.expand_dims, but that seems inefficient to me. I'd prefer to find some way to tweak the einsum to output what I'm after.
Is this posible?
I can wrap the result in np.expand_dims, but that seems inefficient to me
Adding a dimension in numpy is at worst O(ndim), so basically free. Crucially, the actually data is not touched - all that happens is that the .strides and .shape tuples get an extra element each
There is no way right now to use einsum to directly get what you want.
You could try to make a pull-request against numpy to support something like ijk, ijk -> i1k, if you really think it improves readability
I have some data represented in a 1300x1341 matrix. I would like to split this matrix in several pieces (e.g. 9) so that I can loop over and process them. The data needs to stay ordered in the sense that x[0,1] stays below (or above if you like) x[0,0] and besides x[1,1].
Just like if you had imaged the data, you could draw 2 vertical and 2 horizontal lines over the image to illustrate the 9 parts.
If I use numpys reshape (eg. matrix.reshape(9,260,745) or any other combination of 9,260,745) it doesn't yield the required structure since the above mentioned ordering is lost...
Did I misunderstand the reshape method or can it be done this way?
What other pythonic/numpy way is there to do this?
Sounds like you need to use numpy.split() which has its documentation here ... or perhaps its sibling numpy.array_split() here. They are for splitting an array into equal subsections without re-arranging the numbers like reshape does,
I haven't tested this but something like:
numpy.array_split(numpy.zeros((1300,1341)), 9)
should do the trick.
reshape, to quote its docs,
Gives a new shape to an array without
changing its data.
In other words, it does not move the array's data around at all -- it just affects the array's dimension. You, on the other hand, seem to require slicing; again quoting:
It is possible to slice and stride
arrays to extract arrays of the same
number of dimensions, but of different
sizes than the original. The slicing
and striding works exactly the same
way it does for lists and tuples
except that they can be applied to
multiple dimensions as well.
So for example thearray[0:260, 0:745] is the "upper leftmost part, thearray[260:520, 0:745] the upper left-of-center part, and so forth. You could have references to the various parts in a list (or dict with appropriate keys) to process them separately.