Skip to content

split up pandas/tests/indexes/test_multi.py #18644 #21514

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 7 commits into from
Jul 3, 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
Prev Previous commit
Next Next commit
addressing comments to pull request #21514 for GH issue #18644
  • Loading branch information
elmq0022 committed Jul 3, 2018
commit 5780b7ee029f61b47a7755a0d4848d233f8f592c
938 changes: 0 additions & 938 deletions pandas/tests/indexes/multi/test_base.py

This file was deleted.

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


import numpy as np
import pandas as pd
import pandas.util.testing as tm
import pytest
from pandas import (CategoricalIndex, DatetimeIndex, Float64Index, Index,
Int64Index, IntervalIndex, MultiIndex, PeriodIndex,
RangeIndex, Series, TimedeltaIndex, UInt64Index, compat,
isna)
from pandas._libs.tslib import iNaT
from pandas.compat import PY3
from pandas.core.indexes.base import InvalidIndexError
from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin
from pandas.compat import PY3, PYPY, lrange, lzip, range, u, long
import numpy as np



def test_numeric_compat(_index):

idx = _index
tm.assert_raises_regex(TypeError, "cannot perform __mul__",
lambda: idx * 1)
tm.assert_raises_regex(TypeError, "cannot perform __rmul__",
lambda: 1 * idx)

div_err = "cannot perform __truediv__" if PY3 \
else "cannot perform __div__"
tm.assert_raises_regex(TypeError, div_err, lambda: idx / 1)
div_err = div_err.replace(' __', ' __r')
tm.assert_raises_regex(TypeError, div_err, lambda: 1 / idx)
tm.assert_raises_regex(TypeError, "cannot perform __floordiv__",
lambda: idx // 1)
tm.assert_raises_regex(TypeError, "cannot perform __rfloordiv__",
lambda: 1 // idx)


def test_logical_compat(_index):
idx = _index
tm.assert_raises_regex(TypeError, 'cannot perform all',
lambda: idx.all())
tm.assert_raises_regex(TypeError, 'cannot perform any',
lambda: idx.any())


def test_boolean_context_compat(_index):

# boolean context compat
idx = _index

def f():
if idx:
pass

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you change to do this with with

Copy link
Contributor Author

@elmq0022 elmq0022 Jun 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not following here. What is the need to use a context manager here? None of the functions seems to have a valid __enter__ or __exit__ methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want something like with pytest.raises(ValueError):?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep exactly

tm.assert_raises_regex(ValueError, 'The truth value of a', f)


def test_boolean_context_compat2():

# boolean context compat
# GH7897
i1 = MultiIndex.from_tuples([('A', 1), ('A', 2)])
i2 = MultiIndex.from_tuples([('A', 1), ('A', 3)])
common = i1.intersection(i2)

def f():
if common:
pass

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

tm.assert_raises_regex(ValueError, 'The truth value of a', f)


def test_inplace_mutation_resets_values():
levels = [['a', 'b', 'c'], [4]]
levels2 = [[1, 2, 3], ['a']]
labels = [[0, 1, 0, 2, 2, 0], [0, 0, 0, 0, 0, 0]]

mi1 = MultiIndex(levels=levels, labels=labels)
mi2 = MultiIndex(levels=levels2, labels=labels)
vals = mi1.values.copy()
vals2 = mi2.values.copy()

assert mi1._tuples is not None

# Make sure level setting works
new_vals = mi1.set_levels(levels2).values
tm.assert_almost_equal(vals2, new_vals)

# Non-inplace doesn't kill _tuples [implementation detail]
tm.assert_almost_equal(mi1._tuples, vals)

# ...and values is still same too
tm.assert_almost_equal(mi1.values, vals)

# Inplace should kill _tuples
mi1.set_levels(levels2, inplace=True)
tm.assert_almost_equal(mi1.values, vals2)

# Make sure label setting works too
labels2 = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]
exp_values = np.empty((6,), dtype=object)
exp_values[:] = [(long(1), 'a')] * 6

# Must be 1d array of tuples
assert exp_values.shape == (6,)
new_values = mi2.set_labels(labels2).values

# Not inplace shouldn't change
tm.assert_almost_equal(mi2._tuples, vals2)

# Should have correct values
tm.assert_almost_equal(exp_values, new_values)

# ...and again setting inplace should kill _tuples, etc
mi2.set_labels(labels2, inplace=True)
tm.assert_almost_equal(mi2.values, new_values)


def test_ndarray_compat_properties(_index, _compat_props):
idx = _index
assert idx.T.equals(idx)
assert idx.transpose().equals(idx)

values = idx.values
for prop in _compat_props:
assert getattr(idx, prop) == getattr(values, prop)

# test for validity
idx.nbytes
idx.values.nbytes


def test_compat(indices):
assert indices.tolist() == list(indices)

def test_pickle_compat_construction(_holder):
# this is testing for pickle compat
if _holder is None:
return

# need an object to create with
pytest.raises(TypeError, _holder)
31 changes: 31 additions & 0 deletions pandas/tests/indexes/multi/test_constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,3 +476,34 @@ def test_from_product_iterator():
with tm.assert_raises_regex(
TypeError, "Input must be a list / sequence of iterables."):
MultiIndex.from_product(0)


def test_create_index_existing_name(_index):

# GH11193, when an existing index is passed, and a new name is not
# specified, the new index should inherit the previous object name
index = _index
index.names = ['foo', 'bar']
result = pd.Index(index)
tm.assert_index_equal(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

write the expected out on a separate line

result, Index(Index([('foo', 'one'), ('foo', 'two'),
('bar', 'one'), ('baz', 'two'),
('qux', 'one'), ('qux', 'two')],
dtype='object'),
names=['foo', 'bar']))

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']))

def test_tuples_with_name_string():
# GH 15110 and GH 14848

li = [(0, 0, 1), (0, 1, 0), (1, 0, 0)]
with pytest.raises(ValueError):
pd.Index(li, name='abc')
with pytest.raises(ValueError):
pd.Index(li, name='a')
102 changes: 102 additions & 0 deletions pandas/tests/indexes/multi/test_contains.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import pandas as pd
from pandas import MultiIndex
import pytest
from pandas.compat import PY3, PYPY, lrange, lzip, range, u
import numpy as np
import pandas.util.testing as tm


def test_contains_top_level():
Expand All @@ -25,3 +29,101 @@ def test_contains(_index):
assert ('foo', 'two') in _index
assert ('bar', 'two') not in _index
assert None not in _index


@pytest.mark.skipif(not PYPY, reason="tuples cmp recursively on PyPy")
def test_isin_nan_pypy():
idx = MultiIndex.from_arrays([['foo', 'bar'], [1.0, np.nan]])
tm.assert_numpy_array_equal(idx.isin([('bar', np.nan)]),
np.array([False, True]))
tm.assert_numpy_array_equal(idx.isin([('bar', float('nan'))]),
np.array([False, True]))


def test_isin():
values = [('foo', 2), ('bar', 3), ('quux', 4)]

idx = MultiIndex.from_arrays([['qux', 'baz', 'foo', 'bar'], np.arange(
4)])
result = idx.isin(values)
expected = np.array([False, False, True, True])
tm.assert_numpy_array_equal(result, expected)

# empty, return dtype bool
idx = MultiIndex.from_arrays([[], []])
result = idx.isin(values)
assert len(result) == 0
assert result.dtype == np.bool_


@pytest.mark.skipif(PYPY, reason="tuples cmp recursively on PyPy")
def test_isin_nan_not_pypy():
idx = MultiIndex.from_arrays([['foo', 'bar'], [1.0, np.nan]])
tm.assert_numpy_array_equal(idx.isin([('bar', np.nan)]),
np.array([False, False]))
tm.assert_numpy_array_equal(idx.isin([('bar', float('nan'))]),
np.array([False, False]))


def test_isin_level_kwarg():
idx = MultiIndex.from_arrays([['qux', 'baz', 'foo', 'bar'], np.arange(
4)])

vals_0 = ['foo', 'bar', 'quux']
vals_1 = [2, 3, 10]

expected = np.array([False, False, True, True])
tm.assert_numpy_array_equal(expected, idx.isin(vals_0, level=0))
tm.assert_numpy_array_equal(expected, idx.isin(vals_0, level=-2))

tm.assert_numpy_array_equal(expected, idx.isin(vals_1, level=1))
tm.assert_numpy_array_equal(expected, idx.isin(vals_1, level=-1))

pytest.raises(IndexError, idx.isin, vals_0, level=5)
pytest.raises(IndexError, idx.isin, vals_0, level=-5)

pytest.raises(KeyError, idx.isin, vals_0, level=1.0)
pytest.raises(KeyError, idx.isin, vals_1, level=-1.0)
pytest.raises(KeyError, idx.isin, vals_1, level='A')

idx.names = ['A', 'B']
tm.assert_numpy_array_equal(expected, idx.isin(vals_0, level='A'))
tm.assert_numpy_array_equal(expected, idx.isin(vals_1, level='B'))

pytest.raises(KeyError, idx.isin, vals_1, level='C')


def test_hasnans_isnans(named_index):
# GH 11343, added tests for hasnans / isnans
for name, index in named_index.items():
if isinstance(index, MultiIndex):
pass
else:
idx = index.copy()

# cases in indices doesn't include NaN
expected = np.array([False] * len(idx), dtype=bool)
tm.assert_numpy_array_equal(idx._isnan, expected)
assert not idx.hasnans

idx = index.copy()
values = idx.values

if len(index) == 0:
continue
elif isinstance(index, DatetimeIndexOpsMixin):
values[1] = iNaT
elif isinstance(index, (Int64Index, UInt64Index)):
continue
else:
values[1] = np.nan

if isinstance(index, PeriodIndex):
idx = index.__class__(values, freq=index.freq)
else:
idx = index.__class__(values)

expected = np.array([False] * len(idx), dtype=bool)
expected[1] = True
tm.assert_numpy_array_equal(idx._isnan, expected)
assert idx.hasnans
20 changes: 9 additions & 11 deletions pandas/tests/indexes/multi/test_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,9 @@
import pytest
from pandas import DataFrame, MultiIndex, date_range
from pandas.compat import PY3, range

from pandas.util.testing import assert_almost_equal


def test_tuples_with_name_string():
# GH 15110 and GH 14848

li = [(0, 0, 1), (0, 1, 0), (1, 0, 0)]
with pytest.raises(ValueError):
pd.Index(li, name='abc')
with pytest.raises(ValueError):
pd.Index(li, name='a')


def test_tolist(_index):
result = _index.tolist()
exp = list(_index.values)
Expand Down Expand Up @@ -150,3 +139,12 @@ def test_roundtrip_pickle_with_tz():
], names=['one', 'two', 'three'])
unpickled = tm.round_trip_pickle(index)
assert index.equal_levels(unpickled)


def test_pickle(indices):
unpickled = tm.round_trip_pickle(indices)
assert indices.equals(unpickled)
original_name, indices.name = indices.name, 'foo'
unpickled = tm.round_trip_pickle(indices)
assert indices.equals(unpickled)
indices.name = original_name
Loading