Skip to content

Commit c9f9ee3

Browse files
elmq0022jreback
authored andcommitted
CLN: Address MulitIndex Test Follow Ups in Issue #21918 (#21928)
1 parent 171076c commit c9f9ee3

15 files changed

+708
-778
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,328 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import numpy as np
4+
import pandas as pd
5+
import pandas.util.testing as tm
16
import pytest
7+
from pandas import Index, MultiIndex, date_range, period_range
8+
from pandas.compat import lrange
29

310

411
def test_shift(idx):
512

613
# GH8083 test the base class for shift
714
pytest.raises(NotImplementedError, idx.shift, 1)
815
pytest.raises(NotImplementedError, idx.shift, 1, 2)
16+
17+
18+
def test_bounds(idx):
19+
idx._bounds
20+
21+
22+
def test_groupby(idx):
23+
groups = idx.groupby(np.array([1, 1, 1, 2, 2, 2]))
24+
labels = idx.get_values().tolist()
25+
exp = {1: labels[:3], 2: labels[3:]}
26+
tm.assert_dict_equal(groups, exp)
27+
28+
# GH5620
29+
groups = idx.groupby(idx)
30+
exp = {key: [key] for key in idx}
31+
tm.assert_dict_equal(groups, exp)
32+
33+
34+
def test_truncate():
35+
major_axis = Index(lrange(4))
36+
minor_axis = Index(lrange(2))
37+
38+
major_labels = np.array([0, 0, 1, 2, 3, 3])
39+
minor_labels = np.array([0, 1, 0, 1, 0, 1])
40+
41+
index = MultiIndex(levels=[major_axis, minor_axis],
42+
labels=[major_labels, minor_labels])
43+
44+
result = index.truncate(before=1)
45+
assert 'foo' not in result.levels[0]
46+
assert 1 in result.levels[0]
47+
48+
result = index.truncate(after=1)
49+
assert 2 not in result.levels[0]
50+
assert 1 in result.levels[0]
51+
52+
result = index.truncate(before=1, after=2)
53+
assert len(result.levels[0]) == 2
54+
55+
# after < before
56+
pytest.raises(ValueError, index.truncate, 3, 1)
57+
58+
59+
def test_where():
60+
i = MultiIndex.from_tuples([('A', 1), ('A', 2)])
61+
62+
def f():
63+
i.where(True)
64+
65+
pytest.raises(NotImplementedError, f)
66+
67+
68+
def test_where_array_like():
69+
i = MultiIndex.from_tuples([('A', 1), ('A', 2)])
70+
klasses = [list, tuple, np.array, pd.Series]
71+
cond = [False, True]
72+
73+
for klass in klasses:
74+
def f():
75+
return i.where(klass(cond))
76+
pytest.raises(NotImplementedError, f)
77+
78+
# TODO: reshape
79+
80+
81+
def test_reorder_levels(idx):
82+
# this blows up
83+
tm.assert_raises_regex(IndexError, '^Too many levels',
84+
idx.reorder_levels, [2, 1, 0])
85+
86+
87+
def test_numpy_repeat():
88+
reps = 2
89+
numbers = [1, 2, 3]
90+
names = np.array(['foo', 'bar'])
91+
92+
m = MultiIndex.from_product([
93+
numbers, names], names=names)
94+
expected = MultiIndex.from_product([
95+
numbers, names.repeat(reps)], names=names)
96+
tm.assert_index_equal(np.repeat(m, reps), expected)
97+
98+
msg = "the 'axis' parameter is not supported"
99+
tm.assert_raises_regex(
100+
ValueError, msg, np.repeat, m, reps, axis=1)
101+
102+
103+
def test_append_mixed_dtypes():
104+
# GH 13660
105+
dti = date_range('2011-01-01', freq='M', periods=3, )
106+
dti_tz = date_range('2011-01-01', freq='M', periods=3, tz='US/Eastern')
107+
pi = period_range('2011-01', freq='M', periods=3)
108+
109+
mi = MultiIndex.from_arrays([[1, 2, 3],
110+
[1.1, np.nan, 3.3],
111+
['a', 'b', 'c'],
112+
dti, dti_tz, pi])
113+
assert mi.nlevels == 6
114+
115+
res = mi.append(mi)
116+
exp = MultiIndex.from_arrays([[1, 2, 3, 1, 2, 3],
117+
[1.1, np.nan, 3.3, 1.1, np.nan, 3.3],
118+
['a', 'b', 'c', 'a', 'b', 'c'],
119+
dti.append(dti),
120+
dti_tz.append(dti_tz),
121+
pi.append(pi)])
122+
tm.assert_index_equal(res, exp)
123+
124+
other = MultiIndex.from_arrays([['x', 'y', 'z'], ['x', 'y', 'z'],
125+
['x', 'y', 'z'], ['x', 'y', 'z'],
126+
['x', 'y', 'z'], ['x', 'y', 'z']])
127+
128+
res = mi.append(other)
129+
exp = MultiIndex.from_arrays([[1, 2, 3, 'x', 'y', 'z'],
130+
[1.1, np.nan, 3.3, 'x', 'y', 'z'],
131+
['a', 'b', 'c', 'x', 'y', 'z'],
132+
dti.append(pd.Index(['x', 'y', 'z'])),
133+
dti_tz.append(pd.Index(['x', 'y', 'z'])),
134+
pi.append(pd.Index(['x', 'y', 'z']))])
135+
tm.assert_index_equal(res, exp)
136+
137+
138+
def test_take(idx):
139+
indexer = [4, 3, 0, 2]
140+
result = idx.take(indexer)
141+
expected = idx[indexer]
142+
assert result.equals(expected)
143+
144+
# TODO: Remove Commented Code
145+
# if not isinstance(idx,
146+
# (DatetimeIndex, PeriodIndex, TimedeltaIndex)):
147+
# GH 10791
148+
with pytest.raises(AttributeError):
149+
idx.freq
150+
151+
152+
def test_take_invalid_kwargs(idx):
153+
idx = idx
154+
indices = [1, 2]
155+
156+
msg = r"take\(\) got an unexpected keyword argument 'foo'"
157+
tm.assert_raises_regex(TypeError, msg, idx.take,
158+
indices, foo=2)
159+
160+
msg = "the 'out' parameter is not supported"
161+
tm.assert_raises_regex(ValueError, msg, idx.take,
162+
indices, out=indices)
163+
164+
msg = "the 'mode' parameter is not supported"
165+
tm.assert_raises_regex(ValueError, msg, idx.take,
166+
indices, mode='clip')
167+
168+
169+
def test_take_fill_value():
170+
# GH 12631
171+
vals = [['A', 'B'],
172+
[pd.Timestamp('2011-01-01'), pd.Timestamp('2011-01-02')]]
173+
idx = pd.MultiIndex.from_product(vals, names=['str', 'dt'])
174+
175+
result = idx.take(np.array([1, 0, -1]))
176+
exp_vals = [('A', pd.Timestamp('2011-01-02')),
177+
('A', pd.Timestamp('2011-01-01')),
178+
('B', pd.Timestamp('2011-01-02'))]
179+
expected = pd.MultiIndex.from_tuples(exp_vals, names=['str', 'dt'])
180+
tm.assert_index_equal(result, expected)
181+
182+
# fill_value
183+
result = idx.take(np.array([1, 0, -1]), fill_value=True)
184+
exp_vals = [('A', pd.Timestamp('2011-01-02')),
185+
('A', pd.Timestamp('2011-01-01')),
186+
(np.nan, pd.NaT)]
187+
expected = pd.MultiIndex.from_tuples(exp_vals, names=['str', 'dt'])
188+
tm.assert_index_equal(result, expected)
189+
190+
# allow_fill=False
191+
result = idx.take(np.array([1, 0, -1]), allow_fill=False,
192+
fill_value=True)
193+
exp_vals = [('A', pd.Timestamp('2011-01-02')),
194+
('A', pd.Timestamp('2011-01-01')),
195+
('B', pd.Timestamp('2011-01-02'))]
196+
expected = pd.MultiIndex.from_tuples(exp_vals, names=['str', 'dt'])
197+
tm.assert_index_equal(result, expected)
198+
199+
msg = ('When allow_fill=True and fill_value is not None, '
200+
'all indices must be >= -1')
201+
with tm.assert_raises_regex(ValueError, msg):
202+
idx.take(np.array([1, 0, -2]), fill_value=True)
203+
with tm.assert_raises_regex(ValueError, msg):
204+
idx.take(np.array([1, 0, -5]), fill_value=True)
205+
206+
with pytest.raises(IndexError):
207+
idx.take(np.array([1, -5]))
208+
209+
210+
def test_iter(idx):
211+
result = list(idx)
212+
expected = [('foo', 'one'), ('foo', 'two'), ('bar', 'one'),
213+
('baz', 'two'), ('qux', 'one'), ('qux', 'two')]
214+
assert result == expected
215+
216+
217+
def test_sub(idx):
218+
219+
first = idx
220+
221+
# - now raises (previously was set op difference)
222+
with pytest.raises(TypeError):
223+
first - idx[-3:]
224+
with pytest.raises(TypeError):
225+
idx[-3:] - first
226+
with pytest.raises(TypeError):
227+
idx[-3:] - first.tolist()
228+
with pytest.raises(TypeError):
229+
first.tolist() - idx[-3:]
230+
231+
232+
def test_map(idx):
233+
# callable
234+
index = idx
235+
236+
# we don't infer UInt64
237+
if isinstance(index, pd.UInt64Index):
238+
expected = index.astype('int64')
239+
else:
240+
expected = index
241+
242+
result = index.map(lambda x: x)
243+
tm.assert_index_equal(result, expected)
244+
245+
246+
@pytest.mark.parametrize(
247+
"mapper",
248+
[
249+
lambda values, idx: {i: e for e, i in zip(values, idx)},
250+
lambda values, idx: pd.Series(values, idx)])
251+
def test_map_dictlike(idx, mapper):
252+
253+
if isinstance(idx, (pd.CategoricalIndex, pd.IntervalIndex)):
254+
pytest.skip("skipping tests for {}".format(type(idx)))
255+
256+
identity = mapper(idx.values, idx)
257+
258+
# we don't infer to UInt64 for a dict
259+
if isinstance(idx, pd.UInt64Index) and isinstance(identity, dict):
260+
expected = idx.astype('int64')
261+
else:
262+
expected = idx
263+
264+
result = idx.map(identity)
265+
tm.assert_index_equal(result, expected)
266+
267+
# empty mappable
268+
expected = pd.Index([np.nan] * len(idx))
269+
result = idx.map(mapper(expected, idx))
270+
tm.assert_index_equal(result, expected)
271+
272+
273+
@pytest.mark.parametrize('func', [
274+
np.exp, np.exp2, np.expm1, np.log, np.log2, np.log10,
275+
np.log1p, np.sqrt, np.sin, np.cos, np.tan, np.arcsin,
276+
np.arccos, np.arctan, np.sinh, np.cosh, np.tanh,
277+
np.arcsinh, np.arccosh, np.arctanh, np.deg2rad,
278+
np.rad2deg
279+
])
280+
def test_numpy_ufuncs(func):
281+
# test ufuncs of numpy 1.9.2. see:
282+
# http://docs.scipy.org/doc/numpy/reference/ufuncs.html
283+
284+
# some functions are skipped because it may return different result
285+
# for unicode input depending on numpy version
286+
287+
# copy and paste from idx fixture as pytest doesn't support
288+
# parameters and fixtures at the same time.
289+
major_axis = Index(['foo', 'bar', 'baz', 'qux'])
290+
minor_axis = Index(['one', 'two'])
291+
major_labels = np.array([0, 0, 1, 2, 3, 3])
292+
minor_labels = np.array([0, 1, 0, 1, 0, 1])
293+
index_names = ['first', 'second']
294+
295+
idx = MultiIndex(
296+
levels=[major_axis, minor_axis],
297+
labels=[major_labels, minor_labels],
298+
names=index_names,
299+
verify_integrity=False
300+
)
301+
302+
with pytest.raises(Exception):
303+
with np.errstate(all='ignore'):
304+
func(idx)
305+
306+
307+
@pytest.mark.parametrize('func', [
308+
np.isfinite, np.isinf, np.isnan, np.signbit
309+
])
310+
def test_numpy_type_funcs(func):
311+
# for func in [np.isfinite, np.isinf, np.isnan, np.signbit]:
312+
# copy and paste from idx fixture as pytest doesn't support
313+
# parameters and fixtures at the same time.
314+
major_axis = Index(['foo', 'bar', 'baz', 'qux'])
315+
minor_axis = Index(['one', 'two'])
316+
major_labels = np.array([0, 0, 1, 2, 3, 3])
317+
minor_labels = np.array([0, 1, 0, 1, 0, 1])
318+
index_names = ['first', 'second']
319+
320+
idx = MultiIndex(
321+
levels=[major_axis, minor_axis],
322+
labels=[major_labels, minor_labels],
323+
names=index_names,
324+
verify_integrity=False
325+
)
326+
327+
with pytest.raises(Exception):
328+
func(idx)
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import numpy as np
4+
import pandas.util.testing as tm
5+
import pytest
6+
from pandas.util.testing import assert_copy
7+
from pandas.core.dtypes.dtypes import CategoricalDtype
8+
9+
10+
def test_astype(idx):
11+
expected = idx.copy()
12+
actual = idx.astype('O')
13+
assert_copy(actual.levels, expected.levels)
14+
assert_copy(actual.labels, expected.labels)
15+
assert [level.name for level in actual.levels] == list(expected.names)
16+
17+
with tm.assert_raises_regex(TypeError, "^Setting.*dtype.*object"):
18+
idx.astype(np.dtype(int))
19+
20+
21+
@pytest.mark.parametrize('ordered', [True, False])
22+
def test_astype_category(idx, ordered):
23+
# GH 18630
24+
msg = '> 1 ndim Categorical are not supported at this time'
25+
with tm.assert_raises_regex(NotImplementedError, msg):
26+
idx.astype(CategoricalDtype(ordered=ordered))
27+
28+
if ordered is False:
29+
# dtype='category' defaults to ordered=False, so only test once
30+
with tm.assert_raises_regex(NotImplementedError, msg):
31+
idx.astype('category')

0 commit comments

Comments
 (0)