pa23057
pa23057

Reputation: 59

numpy insert & append

I have an array:

X   ndarray   180x360

The following does not work

X = numpy.append(X, X[:,0], 1)

because X[:,0] has the wrong dimensions.

Is not this weird?

This way around the problem seems a bit dirty:

X = numpy.append(X, numpy.array(X[:,0],ndmin=2).T, axis=1)

In MATLAB one could just write: X(:,361) = X(:,1) !!!

I came to realize that this works, too:

X = numpy.insert(X, 361, X[:,0], axis=1)

but why append does not work similarly?

Thank you serpents

Upvotes: 0

Views: 2679

Answers (3)

hpaulj
hpaulj

Reputation: 231335

A key difference is that in MATLAB everything has at least 2 dimensions.

>> size(x(:,1))
ans =
   2   1

and as you note, it allows indexing 'beyond-the-end' - way beyond

>> x(:,10)=x(:,1)
x =
   1   2   3   1   0   0   0   0   0   1
   4   5   6   4   0   0   0   0   0   4

But in numpy indexing reduces the dimensions, without the 2d floor:

In [1675]: x = np.ones((3,4),int)
In [1676]: x.shape
Out[1676]: (3, 4)
In [1677]: x[:,0].shape
Out[1677]: (3,)

That means that if I want to replicate a column I need to make sure it is still a column in the concatenate. There are numerous ways of doing that.

x[:,0][:,None] - use of np.newaxis (alias None) is a nice general purpose method. x[:,[0]], x[:,0:1], x[:,0].reshape(-1,1) also have their place.

append is just concatenate that replaces the list of arguments with 2. It's a confusing imitation of the list append. It is written Python so you can read it (as experienced MATLAB coders do).

insert is a more complicated function (also in Python). Adding at the end it does something like:

In [1687]: x.shape
Out[1687]: (3, 4)
In [1688]: res=np.empty((3,5),int)
In [1689]: res[:,:4] = x
In [1690]: res[:,-1] = x[:,0] 

That last assignment works because both sides have the same shape (technically they just have to be broadcastable shapes). So insert doesn't tell us anything about what should or should not work in more basic operations like concatenate.

Upvotes: 0

MSeifert
MSeifert

Reputation: 152587

The reason is that indexing with one integer removes that axis:

>>> X[:, 0].shape
(180,)

That's a one dimensional array, but if you index by giving a start and stop you keep the axis:

>>> X[:, 0:1].shape
(180, 1)

which could be correctly appended to your array:

>>> np.append(a, a[:, 0:1], 1)
array([....])

But all this aside if you find yourself appending and concatenating lots of arrays be warned: These are extremly inefficient. Most of the time it's better to find another way of doing this, for example creating a bigger array in the beginning and then just setting the rows/columns by slicing:

X = np.zeros((180, 361))
X[:, 360] = X[:, 0]  # much more efficient than appending or inserting

Upvotes: 1

wildwilhelm
wildwilhelm

Reputation: 5019

You can create a new axis on X[:,0]:

np.append(X, X[:,0,None], axis=1)

I think the reason why you have to match array shapes is that numpy.append is implemented using concatenate.

Upvotes: 0

Related Questions