2

I'm relatively new to python but I'm trying to understand something which seems basic.

Create a vector:

x = np.linspace(0,2,3)
Out[38]: array([ 0.,  1.,  2.])

now why isn't x[:,0] a value argument?

IndexError: invalid index

It must be x[0]. I have a function I am calling which calculates:

np.sqrt(x[:,0]**2 + x[:,1]**2 + x[:,2]**2)

Why can't what I have just be true regardless of the input? It many other languages, it is independent of there being other rows in the array. Perhaps I misunderstand something fundamental - sorry if so. I'd like to avoid putting:

if len(x) == 1:
    norm = np.sqrt(x[0]**2 + x[1]**2 + x[2]**2)
else:
    norm = np.sqrt(x[:,0]**2 + x[:,1]**2 + x[:,2]**2)

everywhere. Surely there is a way around this... thanks.

Edit: An example of it working in another language is Matlab:

>> b = [1,2,3]
b =
     1     2     3 
>> b(:,1)
ans =
     1
>> b(1)
ans =

     1
Griff
  • 2,064
  • 5
  • 31
  • 47
  • 3
    It can't be true because you've specified an index for dimension 1 and an index for dimension 2 when your array only has one dimension. Python is explicit rather than implicit. Provide an example in another language and we'll help you write interpretation of the array that makes the same implicit assumptions. – Paul May 13 '13 at 19:08
  • 1
    You can write `x.ndim` instead of `len(x)`. It won't make a difference, but it's a clear and readable name. – jorgeca May 13 '13 at 19:32

4 Answers4

8

Perhaps you are looking for this:

np.sqrt(x[...,0]**2 + x[...,1]**2 + x[...,2]**2)

There can be any number of dimensions in place of the ellipsis ...

See also What does the Python Ellipsis object do?, and the docs of NumPy basic slicing

Community
  • 1
  • 1
Janne Karila
  • 24,266
  • 6
  • 53
  • 94
7

It looks like the ellipsis as described by @JanneKarila has answered your question, but I'd like to point out how you might make your code a bit more "numpythonic". It appears you want to handle an n-dimensional array with the shape (d_1, d_2, ..., d_{n-1}, 3), and compute the magnitudes of this collection of three-dimensional vectors, resulting in an (n-1)-dimensional array with shape (d_1, d_2, ..., d_{n-1}). One simple way to do that is to square all the elements, then sum along the last axis, and then take the square root. If x is the array, that calculation can be written np.sqrt(np.sum(x**2, axis=-1)). The following shows a few examples.

x is 1-D, with shape (3,):

In [31]: x = np.array([1.0, 2.0, 3.0])

In [32]: np.sqrt(np.sum(x**2, axis=-1))
Out[32]: 3.7416573867739413

x is 2-D, with shape (2, 3):

In [33]: x = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])

In [34]: x
Out[34]: 
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])

In [35]: np.sqrt(np.sum(x**2, axis=-1))
Out[35]: array([ 3.74165739,  8.77496439])

x is 3-D, with shape (2, 2, 3):

In [36]: x = np.arange(1.0, 13.0).reshape(2,2,3)

In [37]: x
Out[37]: 
array([[[  1.,   2.,   3.],
        [  4.,   5.,   6.]],

       [[  7.,   8.,   9.],
        [ 10.,  11.,  12.]]])

In [38]: np.sqrt(np.sum(x**2, axis=-1))
Out[38]: 
array([[  3.74165739,   8.77496439],
       [ 13.92838828,  19.10497317]])
Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
  • Ah, this is much nicer than calling `np.atleast_2d` and summing along the first axis as in my answer. – jorgeca May 13 '13 at 21:10
3

I tend to solve this is by writing

x = np.atleast_2d(x)
norm = np.sqrt(x[:,0]**2 + x[:,1]**2 + x[:,2]**2)

Matlab doesn't have 1D arrays, so b=[1 2 3] is still a 2D array and indexing with two dimensions makes sense. It can be a novel concept for you, but they're quite useful in fact (you can stop worrying whether you need to multiply by the transpose, insert a row or a column in another array...)

By the way, you could write a fancier, more general norm like this:

x = np.atleast_2d(x)
norm = np.sqrt((x**2).sum(axis=1))
jorgeca
  • 5,482
  • 3
  • 24
  • 36
1

The problem is that x[:,0] in Python isn't the same as in Matlab. If you want to extract the first element in the single row vector you should go with

x[:1] 

This is called a "slice". In this example it means that you take everything in the array from the first element to the element with index 1 (not included).

Remember that Python has zero-based numbering.

Another example may be:

x[0:2] 

which would return the first and the second element of the array.