Skip to content

CLN: Address MulitIndex Test Follow Ups in Issue #21918 #21928

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

Merged
merged 3 commits into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
429 changes: 429 additions & 0 deletions pandas/tests/indexes/multi/test_analytics.py

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions pandas/tests/indexes/multi/test_astype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-

import numpy as np
import pandas.util.testing as tm
from pandas.util.testing import assert_copy


def test_astype(idx):
expected = idx.copy()
actual = idx.astype('O')
assert_copy(actual.levels, expected.levels)
assert_copy(actual.labels, expected.labels)
assert [level.name for level in actual.levels] == list(expected.names)

with tm.assert_raises_regex(TypeError, "^Setting.*dtype.*object"):
idx.astype(np.dtype(int))
128 changes: 75 additions & 53 deletions pandas/tests/indexes/multi/test_constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,29 +234,31 @@ def test_from_arrays_empty():
tm.assert_index_equal(result, expected)


def test_from_arrays_invalid_input():
@pytest.mark.parametrize('invalid_array', [
(1),
([1]),
([1, 2]),
([[1], 2]),
('a'),
(['a']),
(['a', 'b']),
([['a'], 'b']),
])
def test_from_arrays_invalid_input(invalid_array):
invalid_inputs = [1, [1], [1, 2], [[1], 2],
'a', ['a'], ['a', 'b'], [['a'], 'b']]
for i in invalid_inputs:
pytest.raises(TypeError, MultiIndex.from_arrays, arrays=i)


def test_from_arrays_different_lengths():
@pytest.mark.parametrize('idx1, idx2', [
pytest.param([1, 2, 3], ['a', 'b']),
pytest.param([], ['a', 'b']),
pytest.param([1, 2, 3], [])
]
)
def test_from_arrays_different_lengths(idx1, idx2):
# see gh-13599
idx1 = [1, 2, 3]
idx2 = ['a', 'b']
tm.assert_raises_regex(ValueError, '^all arrays must '
'be same length$',
MultiIndex.from_arrays, [idx1, idx2])

idx1 = []
idx2 = ['a', 'b']
tm.assert_raises_regex(ValueError, '^all arrays must '
'be same length$',
MultiIndex.from_arrays, [idx1, idx2])

idx1 = [1, 2, 3]
idx2 = []
tm.assert_raises_regex(ValueError, '^all arrays must '
'be same length$',
MultiIndex.from_arrays, [idx1, idx2])
Expand Down Expand Up @@ -305,35 +307,41 @@ def test_from_tuples_index_values(idx):
assert (result.values == idx.values).all()


def test_from_product_empty():
def test_from_product_empty_zero_levels():
# 0 levels
with tm.assert_raises_regex(
ValueError, "Must pass non-zero number of levels/labels"):
MultiIndex.from_product([])

# 1 level

def test_from_product_empty_one_level():
result = MultiIndex.from_product([[]], names=['A'])
expected = pd.Index([], name='A')
tm.assert_index_equal(result.levels[0], expected)

# 2 levels
l1 = [[], ['foo', 'bar', 'baz'], []]
l2 = [[], [], ['a', 'b', 'c']]

@pytest.mark.parametrize('first, second', [
([], []),
(['foo', 'bar', 'baz'], []),
([], ['a', 'b', 'c']),
])
def test_from_product_empty_two_levels(first, second):
names = ['A', 'B']
for first, second in zip(l1, l2):
result = MultiIndex.from_product([first, second], names=names)
expected = MultiIndex(levels=[first, second],
labels=[[], []], names=names)
tm.assert_index_equal(result, expected)
result = MultiIndex.from_product([first, second], names=names)
expected = MultiIndex(levels=[first, second],
labels=[[], []], names=names)
tm.assert_index_equal(result, expected)


@pytest.mark.parametrize('N', list(range(4)))
def test_from_product_empty_three_levels(N):
# GH12258
names = ['A', 'B', 'C']
for N in range(4):
lvl2 = lrange(N)
result = MultiIndex.from_product([[], lvl2, []], names=names)
expected = MultiIndex(levels=[[], lvl2, []],
labels=[[], [], []], names=names)
tm.assert_index_equal(result, expected)
lvl2 = lrange(N)
result = MultiIndex.from_product([[], lvl2, []], names=names)
expected = MultiIndex(levels=[[], lvl2, []],
labels=[[], [], []], names=names)
tm.assert_index_equal(result, expected)


def test_from_product_invalid_input():
Expand All @@ -352,19 +360,24 @@ def test_from_product_datetimeindex():
tm.assert_numpy_array_equal(mi.values, etalon)


def test_from_product_index_series_categorical():
@pytest.mark.parametrize('ordered', [False, True])
@pytest.mark.parametrize('f', [
lambda x: x,
lambda x: pd.Series(x),
lambda x: x.values
])
def test_from_product_index_series_categorical(ordered, f):
# GH13743
first = ['foo', 'bar']
for ordered in [False, True]:
idx = pd.CategoricalIndex(list("abcaab"), categories=list("bac"),
ordered=ordered)
expected = pd.CategoricalIndex(list("abcaab") + list("abcaab"),
categories=list("bac"),
ordered=ordered)

for arr in [idx, pd.Series(idx), idx.values]:
result = pd.MultiIndex.from_product([first, arr])
tm.assert_index_equal(result.get_level_values(1), expected)
idx = pd.CategoricalIndex(list("abcaab"), categories=list("bac"),
ordered=ordered)
expected = pd.CategoricalIndex(list("abcaab") + list("abcaab"),
categories=list("bac"),
ordered=ordered)

result = pd.MultiIndex.from_product([first, f(idx)])
tm.assert_index_equal(result.get_level_values(1), expected)


def test_from_product():
Expand Down Expand Up @@ -409,19 +422,28 @@ def test_create_index_existing_name(idx):
index = idx
index.names = ['foo', 'bar']
result = pd.Index(index)
tm.assert_index_equal(
result, Index(Index([('foo', 'one'), ('foo', 'two'),
('bar', 'one'), ('baz', 'two'),
('qux', 'one'), ('qux', 'two')],
dtype='object'),
names=['foo', 'bar']))
expected = Index(
Index([
('foo', 'one'), ('foo', 'two'),
('bar', 'one'), ('baz', 'two'),
('qux', 'one'), ('qux', 'two')],
dtype='object'
),
names=['foo', 'bar']
)
tm.assert_index_equal(result, expected)

result = pd.Index(index, names=['A', 'B'])
tm.assert_index_equal(
result,
Index(Index([('foo', 'one'), ('foo', 'two'), ('bar', 'one'),
('baz', 'two'), ('qux', 'one'), ('qux', 'two')],
dtype='object'), names=['A', 'B']))
expected = Index(
Index([
('foo', 'one'), ('foo', 'two'),
('bar', 'one'), ('baz', 'two'),
('qux', 'one'), ('qux', 'two')],
dtype='object'
),
names=['A', 'B']
)
tm.assert_index_equal(result, expected)


def test_tuples_with_name_string():
Expand Down
128 changes: 45 additions & 83 deletions pandas/tests/indexes/multi/test_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from copy import copy, deepcopy

import pandas.util.testing as tm
from pandas import (CategoricalIndex, IntervalIndex, MultiIndex, PeriodIndex,
RangeIndex, Series, compat)
import pytest
from pandas import MultiIndex


def assert_multiindex_copied(copy, original):
Expand Down Expand Up @@ -41,84 +41,46 @@ def test_view(idx):
assert_multiindex_copied(i_view, idx)


def test_copy_name(idx):
# gh-12309: Check that the "name" argument
# passed at initialization is honored.

# TODO: Remove or refactor MultiIndex not tested.
for name, index in compat.iteritems({'idx': idx}):
if isinstance(index, MultiIndex):
continue

first = index.__class__(index, copy=True, name='mario')
second = first.__class__(first, copy=False)

# Even though "copy=False", we want a new object.
assert first is not second

# Not using tm.assert_index_equal() since names differ.
assert index.equals(first)

assert first.name == 'mario'
assert second.name == 'mario'

s1 = Series(2, index=first)
s2 = Series(3, index=second[:-1])

if not isinstance(index, CategoricalIndex):
# See gh-13365
s3 = s1 * s2
assert s3.index.name == 'mario'


def test_ensure_copied_data(idx):
# Check the "copy" argument of each Index.__new__ is honoured
# GH12309
# TODO: REMOVE THIS TEST. MultiIndex is tested seperately as noted below.

for name, index in compat.iteritems({'idx': idx}):
init_kwargs = {}
if isinstance(index, PeriodIndex):
# Needs "freq" specification:
init_kwargs['freq'] = index.freq
elif isinstance(index, (RangeIndex, MultiIndex, CategoricalIndex)):
# RangeIndex cannot be initialized from data
# MultiIndex and CategoricalIndex are tested separately
continue

index_type = index.__class__
result = index_type(index.values, copy=True, **init_kwargs)
tm.assert_index_equal(index, result)
tm.assert_numpy_array_equal(index.values, result.values,
check_same='copy')

if isinstance(index, PeriodIndex):
# .values an object array of Period, thus copied
result = index_type(ordinal=index.asi8, copy=False,
**init_kwargs)
tm.assert_numpy_array_equal(index._ndarray_values,
result._ndarray_values,
check_same='same')
elif isinstance(index, IntervalIndex):
# checked in test_interval.py
pass
else:
result = index_type(index.values, copy=False, **init_kwargs)
tm.assert_numpy_array_equal(index.values, result.values,
check_same='same')
tm.assert_numpy_array_equal(index._ndarray_values,
result._ndarray_values,
check_same='same')


def test_copy_and_deepcopy(indices):

if isinstance(indices, MultiIndex):
return
for func in (copy, deepcopy):
idx_copy = func(indices)
assert idx_copy is not indices
assert idx_copy.equals(indices)

new_copy = indices.copy(deep=True, name="banana")
assert new_copy.name == "banana"
@pytest.mark.parametrize('func', [copy, deepcopy])
def test_copy_and_deepcopy(func):

idx = MultiIndex(
levels=[['foo', 'bar'], ['fizz', 'buzz']],
labels=[[0, 0, 0, 1], [0, 0, 1, 1]],
names=['first', 'second']
)
idx_copy = func(idx)
assert idx_copy is not idx
assert idx_copy.equals(idx)


@pytest.mark.parametrize('deep', [True, False])
def test_copy_method(deep):
idx = MultiIndex(
levels=[['foo', 'bar'], ['fizz', 'buzz']],
labels=[[0, 0, 0, 1], [0, 0, 1, 1]],
names=['first', 'second']
)
idx_copy = idx.copy(deep=deep)
assert idx_copy.equals(idx)


@pytest.mark.parametrize('deep', [True, False])
@pytest.mark.parametrize('kwarg, value', [
('names', ['thrid', 'fourth']),
('levels', [['foo2', 'bar2'], ['fizz2', 'buzz2']]),
('labels', [[1, 0, 0, 0], [1, 1, 0, 0]])
])
def test_copy_method_kwargs(deep, kwarg, value):
# gh-12309: Check that the "name" argument as well other kwargs are honored
idx = MultiIndex(
levels=[['foo', 'bar'], ['fizz', 'buzz']],
labels=[[0, 0, 0, 1], [0, 0, 1, 1]],
names=['first', 'second']
)

idx_copy = idx.copy(**{kwarg: value, 'deep': deep})
if kwarg == 'names':
assert getattr(idx_copy, kwarg) == value
else:
assert list(list(i) for i in getattr(idx_copy, kwarg)) == value
5 changes: 0 additions & 5 deletions pandas/tests/indexes/multi/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,6 @@ def test_repr_roundtrip():
tm.assert_index_equal(result, mi_u, exact=True)


def test_str():
# tested elsewhere
pass


def test_unicode_string_with_unicode():
d = {"a": [u("\u05d0"), 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]}
idx = pd.DataFrame(d).set_index(["a", "b"]).index
Expand Down
Loading