Skip to content

REGR: assigning scalar with a length no longer works #26333

Open
@jorisvandenbossche

Description

@jorisvandenbossche

Assigning a value to a single location in a DataFrame (using .loc with scalar indexers) started to fail with "values with a length".

Consider the following example:

In [1]: df = pd.DataFrame({'a': [1, 2, 3], 'b': [(1, 2), (1, 2, 3), (3, 4)]})

In [2]: df
Out[2]: 
   a          b
0  1     (1, 2)
1  2  (1, 2, 3)
2  3     (3, 4)

In [3]: df.loc[0, 'b'] = (7, 8, 9)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-a2d59e11519a> in <module>
----> 1 df.loc[0, 'b'] = (7, 8, 9)

~/miniconda3/lib/python3.7/site-packages/pandas/core/indexing.py in __setitem__(self, key, value)
    187             key = com._apply_if_callable(key, self.obj)
    188         indexer = self._get_setitem_indexer(key)
--> 189         self._setitem_with_indexer(indexer, value)
    190 
    191     def _validate_key(self, key, axis):

~/miniconda3/lib/python3.7/site-packages/pandas/core/indexing.py in _setitem_with_indexer(self, indexer, value)
    604 
    605                     if len(labels) != len(value):
--> 606                         raise ValueError('Must have equal len keys and value '
    607                                          'when setting with an iterable')
    608 

ValueError: Must have equal len keys and value when setting with an iterable

This raises on 0.23.4 - master, but worked in 0.20.3 - 0.22.0 (the ones I tested):

In [1]: pd.__version__
Out[1]: '0.22.0'

In [2]: df = pd.DataFrame({'a': [1, 2, 3], 'b': [(1, 2), (1, 2, 3), (3, 4)]})

In [3]: df
Out[3]: 
   a          b
0  1     (1, 2)
1  2  (1, 2, 3)
2  3     (3, 4)

In [4]: df.loc[0, 'b'] = (7, 8, 9)

In [5]: df
Out[5]: 
   a          b
0  1  (7, 8, 9)
1  2  (1, 2, 3)
2  3     (3, 4)

Related to #25806

We don't have very robust support in general for list-like values, but, for the specific case above of updating a single value, I don't think there is anything ambiguous about it? You are updating a single value, so the passed value should simply be put in that place?

Note, the above is with tuples. But, there are also custom objects like MultiPolygons that represent single objects, but do define a __len__ ..

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugIndexingRelated to indexing on series/frames, not to indexes themselvesNested DataData where the values are collections (lists, sets, dicts, objects, etc.).RegressionFunctionality that used to work in a prior pandas version

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions