-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
BUG: assignment to multiple columns when some column do not exist #29334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
25ad422
b8d3c48
660d0f2
d7184e7
a509eb5
e908282
26ba2a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2687,6 +2687,7 @@ def _setitem_array(self, key, value): | |
for k1, k2 in zip(key, value.columns): | ||
self[k1] = value[k2] | ||
else: | ||
self.loc._ensure_listlike_indexer(key, axis=1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it looks like you're also calling this inside _get_setitem_indexer; do you need to also call it here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
indexer = self.loc._get_listlike_indexer( | ||
key, axis=1, raise_missing=False | ||
)[1] | ||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -8,6 +8,7 @@ | |||
from pandas.util._decorators import Appender | ||||
|
||||
from pandas.core.dtypes.common import ( | ||||
is_hashable, | ||||
is_integer, | ||||
is_iterator, | ||||
is_list_like, | ||||
|
@@ -581,6 +582,9 @@ def _get_setitem_indexer(self, key): | |||
""" | ||||
Convert a potentially-label-based key into a positional indexer. | ||||
""" | ||||
if self.name == "loc": | ||||
self._ensure_listlike_indexer(key) | ||||
|
||||
if self.axis is not None: | ||||
return self._convert_tuple(key, is_setter=True) | ||||
|
||||
|
@@ -611,6 +615,42 @@ def _get_setitem_indexer(self, key): | |||
raise | ||||
raise IndexingError(key) from e | ||||
|
||||
def _ensure_listlike_indexer(self, key, axis=None): | ||||
""" | ||||
Ensure that a list-like of column labels are all present by adding them if | ||||
they do not already exist. | ||||
|
||||
Parameters | ||||
---------- | ||||
key : _LocIndexer key or list-like of column labels | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i dont think key being a _LocIndexer object makes sense There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? pandas/pandas/core/indexing.py Line 586 in d7184e7
|
||||
Target labels. | ||||
axis : key axis if known | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it looks like axis isnt used here, is it necessary? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's used at pandas/pandas/core/indexing.py Line 642 in d7184e7
For rationale of coding this way, see #29334 (comment). |
||||
""" | ||||
column_axis = 1 | ||||
|
||||
# column only exists in 2-dimensional DataFrame | ||||
if self.ndim != 2: | ||||
return | ||||
|
||||
if isinstance(key, tuple): | ||||
# key may be a tuple if key is a _LocIndexer key | ||||
# in that case, set key to the column part of key | ||||
key = key[column_axis] | ||||
axis = column_axis | ||||
|
||||
if ( | ||||
axis == column_axis | ||||
and not isinstance(self.obj.columns, ABCMultiIndex) | ||||
and is_list_like_indexer(key) | ||||
and not com.is_bool_indexer(key) | ||||
and all(is_hashable(k) for k in key) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think the hashable check you can skip and the calls below will take care of it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If no hashable check is performed here, some test cases fail , eg. pandas/pandas/tests/indexing/test_indexing.py Line 112 in d7184e7
|
||||
): | ||||
for k in key: | ||||
try: | ||||
self.obj[k] | ||||
except KeyError: | ||||
self.obj[k] = np.nan | ||||
|
||||
def __setitem__(self, key, value): | ||||
if isinstance(key, tuple): | ||||
key = tuple(com.apply_if_callable(x, self.obj) for x in key) | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this to the section where we od api-breaking changes.