Kartik
Kartik

Reputation: 8683

TypeError: len() of unsized object when comparing and I cannot make sense of it

I am trying to select sensors by placing a box around their geographic coordinates:

In [1]: lat_min, lat_max = lats(data)
        lon_min, lon_max = lons(data)

        print(np.around(np.array([lat_min, lat_max, lon_min, lon_max]), 5))
Out[1]: [ 32.87248  33.10181 -94.37297 -94.21224]

In [2]: select_sens = sens[(lat_min<=sens['LATITUDE']) & (sens['LATITUDE']<=lat_max) &
                           (lon_min<=sens['LONGITUDE']) & (sens['LONGITUDE']<=lon_max)].copy()
Out[2]: ---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-7881f6717415> in <module>()
      4 lon_min, lon_max = lons(data)
      5 select_sens = sens[(lat_min<=sens['LATITUDE']) & (sens['LATITUDE']<=lat_max) &
----> 6                    (lon_min<=sens['LONGITUDE']) & (sens['LONGITUDE']<=lon_max)].copy()
      7 sens_data = data[data['ID'].isin(select_sens['ID'])].copy()
      8 sens_data.describe()

/home/kartik/miniconda3/lib/python3.5/site-packages/pandas/core/ops.py in wrapper(self, other, axis)
    703             return NotImplemented
    704         elif isinstance(other, (np.ndarray, pd.Index)):
--> 705             if len(self) != len(other):
    706                 raise ValueError('Lengths must match to compare')
    707             return self._constructor(na_op(self.values, np.asarray(other)),

TypeError: len() of unsized object

Of course, sens is a pandas DataFrame. Even when I use .where() it raises the same error. I am completely stumped, because it is a simple comparison that shouldn't raise any errors. Even the data types match:

In [3]: sens.dtypes
Out[3]: ID              object
        COUNTRY         object
        STATE           object
        COUNTY          object
        LENGTH         float64
        NUMBER          object
        NAME            object
        LATITUDE       float64
        LONGITUDE      float64
        dtype: object

So what is going on?!?

-----EDIT------ As per Ethan Furman's answer, I made the following changes:

In [2]: select_sens = sens[([lat_min]<=sens['LATITUDE']) & (sens['LATITUDE']<=[lat_max]) &
                           ([lon_min]<=sens['LONGITUDE']) & (sens['LONGITUDE']<=[lon_max])].copy()

And (drumroll) it worked... But why?

Upvotes: 3

Views: 9738

Answers (2)

Juan Ossa
Juan Ossa

Reputation: 1213

I found a similar issue and think the problem may be related to the Python version you are using.

I wrote my code in Spyder Python 3.6.1 |Anaconda 4.4.0 (64-bit)

but then passed it to someone using Spyder but Python 3.5.2 |Anaconda 4.2.0 (64-bit)

I had one numpy.float64 object (as far as i understand, similar to lat_min, lat_max, lon_min and lon_max in your code) MinWD.MinWD[i]

In [92]: type(MinWD.MinWD[i])
Out[92]: numpy.float64

and a Pandas data frame WatDemandCur with one column called Percentages

In [96]: type(WatDemandCur)
Out[96]: pandas.core.frame.DataFrame

In [98]: type(WatDemandCur['Percentages'])
Out[98]: pandas.core.series.Series

and i wanted to do the following comparison

In [99]: MinWD.MinWD[i]==WatDemandCur.Percentages

There was no problem with this line when running the code in my machine (Python 3.6.1)

But my friend got something similar to you in (Python 3.5.2)

MinWD.MinWD[i]==WatDemandCur.Percentages
Traceback (most recent call last):

  File "<ipython-input-99-3e762b849176>", line 1, in <module>
    MinWD.MinWD[i]==WatDemandCur.Percentages

  File "C:\Program Files\Anaconda3\lib\site-packages\pandas\core\ops.py", line 741, in wrapper
    if len(self) != len(other):

TypeError: len() of unsized object

My solution to his problem was to change the code to

[MinWD.MinWD[i]==x for x in WatDemandCur.Percentages] 

and it worked in both versions!

With this and your evidence, i would assume that it is not possible to compare numpy.float64 and perhaps numpy.integers objects with Pandas Series, and this could be partly related to the fact that the former have no len function.

Just for curiosity, i did some tests with float and integer objects (please tell the difference with numpy.float64 object)

In [122]: Temp=1

In [123]: Temp2=1.0

In [124]: type(Temp)
Out[124]: int

In [125]: type(Temp2)
Out[125]: float

In [126]: len(Temp)
Traceback (most recent call last):

  File "<ipython-input-126-dc80ab11ca9c>", line 1, in <module>
    len(Temp)

TypeError: object of type 'int' has no len()


In [127]: len(Temp2)
Traceback (most recent call last):

  File "<ipython-input-127-a1b836f351d2>", line 1, in <module>
    len(Temp2)

TypeError: object of type 'float' has no len()

Temp==WatDemandCur.Percentages

Temp2==WatDemandCur.Percentages

Both worked!

Conclusions

  1. In another python version your code should work!
  2. The problem with the comparison is specific for numpy.floats and perhaps numpy.integers
  3. When you include [] or when I create the list with my solution, the type of object is changed from a numpy.float to a list, and in this way it works fine.
  4. Although the problem seems to be related to the fact that numpy.float64 objects have no len function, floats and integers, which do not have a len function either, do work.

Hope some of this works for you or someone else facing a similar issue.

Upvotes: 1

Ethan Furman
Ethan Furman

Reputation: 69021

I'm not familiar with NumPy nor Pandas, but the error is saying that one of the objects in the comparison if len(self) != len(other) does not have a __len__ method and therefore has no length.

Try doing print(sens_data) to see if you get a similar error.

Upvotes: 3

Related Questions