BUG: in Python3 MultiIndex.from_tuples cannot take "zipped" tuples#18440
BUG: in Python3 MultiIndex.from_tuples cannot take "zipped" tuples#18440jreback merged 2 commits intopandas-dev:masterfrom
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
| MultiIndex.from_product : Make a MultiIndex from cartesian product | ||
| of iterables | ||
| """ | ||
| if not hasattr(tuples, '__len__'): |
There was a problem hiding this comment.
would just do
if not is_list_like(tuples):
raise TypeError...
elif is_iterator(tuples):
tuples = list(tuples)
pandas/core/indexes/multi.py
Outdated
| """ | ||
| if not hasattr(tuples, '__len__'): | ||
| try: | ||
| iter(tuples) # if iterable, then it's iterator or generator |
There was a problem hiding this comment.
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 |
jreback
left a comment
There was a problem hiding this comment.
some error context comments. otherwise lgtm. ping on green.
pandas/core/indexes/multi.py
Outdated
| of iterables | ||
| """ | ||
| if not is_list_like(arrays): | ||
| raise TypeError("Inappropriate input for list of arrays.") |
There was a problem hiding this comment.
make a more user-friendly message, maybe
input must be a list-like of arrays
pandas/core/indexes/multi.py
Outdated
| of iterables | ||
| """ | ||
| if not is_list_like(tuples): | ||
| raise TypeError('Inappropriate input for tuples.') |
| from pandas.core.categorical import _factorize_from_iterables | ||
| from pandas.core.reshape.util import cartesian_product | ||
|
|
||
| if not is_list_like(iterables): |
pandas/tests/indexes/test_multi.py
Outdated
| # list of arrays as input | ||
| result = MultiIndex.from_arrays(arrays) | ||
| assert list(result) == list(self.index) | ||
| # iterator as input |
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 |
| expected = MultiIndex(levels=[[1, 3], [2, 4]], | ||
| labels=[[0, 1], [0, 1]], | ||
| names=['a', 'b']) | ||
| # input tuples |
jreback
left a comment
There was a problem hiding this comment.
pls rebase as well. lgtm. ping on green.
| tm.assert_index_equal(result, expected) | ||
| assert result.names == names | ||
|
|
||
| # iterator as input |
There was a problem hiding this comment.
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
| of iterables | ||
| """ | ||
| if not is_list_like(tuples): | ||
| raise TypeError('Input must be a list /sequence of tuple-likes.') |
| labels=[[0, 1], [0, 1]], | ||
| names=['a', 'b']) | ||
|
|
||
| # input tuples |
pandas/tests/indexes/test_multi.py
Outdated
| names=['a', 'b']) | ||
|
|
||
| # input tuples | ||
| res1 = MultiIndex.from_tuples(((1, 2), (3, 4)), names=['a', 'b']) |
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']) |
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.
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 |
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.
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.
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) |
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 |
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) |
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 |
|
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