Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How detect length of a numpy array with only one element?

I am reading in a file using numpy.genfromtxt which brings in columns of both strings and numeric values. One thing I need to do is detect the length of the input. This is all fine provided there are more than one value read into each array.

But...if there is only one element in the resulting array, the logic fails. I can recreate an example here:

import numpy as np
a = np.array(2.3)

len(a) returns an error saying:

TypeError: len() of unsized object

however, If a has 2 or more elements, len() behaves as one would expect.

import numpy as np
a = np.array([2.3,3.6])

len(a) returns 2

My concern here is, if I use some strange exception handling, I can't distinguish between a being empty and a having length = 1.

EDIT: @noskio suggested setting a = np.array([2.3]). The problem is, the actual genesis of a is by using numpy.genfromtxt. The code looks like this:

import numpy as np
indata = np.genfromtxt(some_filename, names=True,dtype=None)
a = indata['one_col_headername']

As a result, if indata is only one row in the file, a is a 0-d array.

like image 749
mishaF Avatar asked Dec 30 '10 19:12

mishaF


3 Answers

If you need a one-liner (assuming the answer you are expecting is 1):

In [1]: import numpy as np

In [2]: a = np.array(2.3)

In [3]: len(np.atleast_1d(a))
Out[3]: 1

This page explains why it was decided to implement 0-dimensional arrays in numpy.

like image 98
pberkes Avatar answered Oct 04 '22 21:10

pberkes


import numpy as np

tests=[np.array(2.3),np.array([]),np.array([2.3]),np.array([2.3,3.6])]

print('{a:30}{s:<10}{l:<10}{sl:<10}'.format(a='repr',s='shape',sl='len(shape)',l='length'))
for a in tests:
    s=a.shape
    l=len(a) if a.shape else 0
    sl=len(s)
    print('{a!r:30}{s:<10}{l:<10}{sl:<10}'.format(a=a,l=l,s=s,sl=sl))

yields

repr                          shape     length    len(shape)
array(2.2999999999999998)     ()        0         0         
array([], dtype=float64)      (0,)      0         1         
array([ 2.3])                 (1,)      1         1         
array([ 2.3,  3.6])           (2,)      2         1        

You can distinguish between an "empty" array (e.g. np.array([])) and a numpy scalar (e.g. np.array(2.3)) by looking at the length of the shape.

like image 44
unutbu Avatar answered Oct 04 '22 19:10

unutbu


It looks like the size property of ndarrays will work in this case if you know that the array is one-dimensional. In my opinion, a.size is a lot more readable than len(np.atleast_1d(a)). However, note that the size property will return the total number of elements in the array if it has more than one dimension:

In [1]: import numpy as np

In [2]: np.array(2.3).size
Out[2]: 1

In [3]: np.array([1, 2]).size
Out[3]: 2

In [4]: np.array([[1,2], [3,4]]).size
Out[4]: 4
like image 44
Brandon Avatar answered Oct 04 '22 20:10

Brandon