-
-
Notifications
You must be signed in to change notification settings - Fork 18.2k
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
BUG: in Python3 MultiIndex.from_tuples cannot take "zipped" tuples #18440
Conversation
Codecov Report
@@ Coverage Diff @@
## master #18440 +/- ##
==========================================
- Coverage 91.36% 91.32% -0.04%
==========================================
Files 163 163
Lines 49700 49764 +64
==========================================
+ Hits 45407 45446 +39
- Misses 4293 4318 +25
Continue to review full report at Codecov.
|
pandas/core/indexes/multi.py
Outdated
@@ -1206,6 +1206,12 @@ def from_tuples(cls, tuples, sortorder=None, names=None): | |||
MultiIndex.from_product : Make a MultiIndex from cartesian product | |||
of iterables | |||
""" | |||
if not hasattr(tuples, '__len__'): |
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.
would just do
if not is_list_like(tuples):
raise TypeError...
elif is_iterator(tuples):
tuples = list(tuples)
pandas/core/indexes/multi.py
Outdated
@@ -1206,6 +1206,12 @@ def from_tuples(cls, tuples, sortorder=None, names=None): | |||
MultiIndex.from_product : Make a MultiIndex from cartesian product | |||
of iterables | |||
""" | |||
if not hasattr(tuples, '__len__'): | |||
try: | |||
iter(tuples) # if iterable, then it's iterator or generator |
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.
needs checking in from_product
and from_arrays
as well.
needs tests that hit all 3 cases
Added the test cases and fix from_tuples/from_arrays/from_product |
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.
some error context comments. otherwise lgtm. ping on green.
pandas/core/indexes/multi.py
Outdated
@@ -1162,6 +1162,11 @@ def from_arrays(cls, arrays, sortorder=None, names=None): | |||
MultiIndex.from_product : Make a MultiIndex from cartesian product | |||
of iterables | |||
""" | |||
if not is_list_like(arrays): | |||
raise TypeError("Inappropriate input for list of arrays.") |
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.
make a more user-friendly message, maybe
input must be a list-like of arrays
pandas/core/indexes/multi.py
Outdated
@@ -1206,6 +1211,11 @@ def from_tuples(cls, tuples, sortorder=None, names=None): | |||
MultiIndex.from_product : Make a MultiIndex from cartesian product | |||
of iterables | |||
""" | |||
if not is_list_like(tuples): | |||
raise TypeError('Inappropriate input for tuples.') |
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.
same (except say tuples)
@@ -1260,6 +1270,11 @@ def from_product(cls, iterables, sortorder=None, names=None): | |||
from pandas.core.categorical import _factorize_from_iterables | |||
from pandas.core.reshape.util import cartesian_product | |||
|
|||
if not is_list_like(iterables): |
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.
same
pandas/tests/indexes/test_multi.py
Outdated
result = MultiIndex.from_arrays(arrays) | ||
assert list(result) == list(self.index) | ||
# iterator as input |
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.
blank line here
pandas/tests/indexes/test_multi.py
Outdated
# iterator as input | ||
result2 = MultiIndex.from_arrays(iter(arrays)) | ||
assert list(result2) == list(self.index) | ||
# invlide iterator input |
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.
same
pandas/tests/indexes/test_multi.py
Outdated
expected = MultiIndex(levels=[[1, 3], [2, 4]], | ||
labels=[[0, 1], [0, 1]], | ||
names=['a', 'b']) | ||
# input tuples |
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.
same
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.
pls rebase as well. lgtm. ping on green.
pandas/tests/indexes/test_multi.py
Outdated
@@ -827,6 +837,16 @@ def test_from_product(self): | |||
tm.assert_index_equal(result, expected) | |||
assert result.names == names | |||
|
|||
# iterator as input |
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.
can you make this a separate test (the added code), and do so for from_product, from_tuples, from_arrays as well, call it something like
test_multiindex_from_product_iterable
and add the issue number to it.
pandas/core/indexes/multi.py
Outdated
@@ -1206,6 +1211,11 @@ def from_tuples(cls, tuples, sortorder=None, names=None): | |||
MultiIndex.from_product : Make a MultiIndex from cartesian product | |||
of iterables | |||
""" | |||
if not is_list_like(tuples): | |||
raise TypeError('Input must be a list /sequence of tuple-likes.') |
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.
need a space after the /
labels=[[0, 1], [0, 1]], | ||
names=['a', 'b']) | ||
|
||
# input tuples |
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.
same (new test)
pandas/tests/indexes/test_multi.py
Outdated
names=['a', 'b']) | ||
|
||
# input tuples | ||
res1 = MultiIndex.from_tuples(((1, 2), (3, 4)), names=['a', 'b']) |
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.
use result =
pandas/tests/indexes/test_multi.py
Outdated
assert res1.equals(expected) | ||
|
||
# input iterator for tuples | ||
res2 = MultiIndex.from_tuples(zip([1, 3], [2, 4]), names=['a', 'b']) |
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.
same
pandas/tests/indexes/test_multi.py
Outdated
# input iterator for tuples | ||
res2 = MultiIndex.from_tuples(zip([1, 3], [2, 4]), names=['a', 'b']) | ||
assert expected.names == res2.names | ||
assert res2.equals(expected) |
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.
use tm.assert_index_equal(result, expected)
for the checking
pandas/tests/indexes/test_multi.py
Outdated
result = MultiIndex.from_arrays(arrays) | ||
assert list(result) == list(self.index) | ||
|
||
# iterator as input |
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.
separate test
pandas/core/indexes/multi.py
Outdated
for lev, lab in zip(self.levels, self.labels): | ||
for idx, (lev, lab) in enumerate(zip(self.levels, self.labels)): | ||
na_idxs = np.where(lab == -1)[0] | ||
|
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.
looks like you picked up another commit.
All build passed. |
pandas/tests/indexes/test_multi.py
Outdated
|
||
# iterator as input | ||
result = MultiIndex.from_arrays(iter(arrays)) | ||
assert list(result) == list(self.index) |
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.
use tm.assert_index_equal
, IOW construct the expected MI
pandas/tests/indexes/test_multi.py
Outdated
|
||
# iterator as input | ||
result = MultiIndex.from_product(iter([first, second]), names=names) | ||
assert result.equals(expected) |
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.
use assert_index_equal
pandas/tests/indexes/test_multi.py
Outdated
|
||
# input tuples | ||
result = MultiIndex.from_tuples(((1, 2), (3, 4)), names=['a', 'b']) | ||
assert expected.names == result.names |
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.
same
pandas/tests/indexes/test_multi.py
Outdated
# input tuples | ||
result = MultiIndex.from_tuples(((1, 2), (3, 4)), names=['a', 'b']) | ||
assert expected.names == result.names | ||
assert result.equals(expected) |
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.
same
pandas/tests/indexes/test_multi.py
Outdated
names=['a', 'b']) | ||
|
||
result = MultiIndex.from_tuples(zip([1, 3], [2, 4]), names=['a', 'b']) | ||
assert expected.names == result.names |
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.
same
thanks @Xbar nice patch and very responsive interactions! |
Thanks! 👍 |
MultiIndex.from_tuples accept zipped tuples in python 3. Ensures compatibility
between 2 and 3.
git diff upstream/master -u -- "*.py" | flake8 --diff