mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-07-02 22:30:48 +00:00
first commit
This commit is contained in:
@ -0,0 +1,87 @@
|
||||
import re
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas.core.dtypes.common import pandas_dtype
|
||||
|
||||
from pandas import Index
|
||||
import pandas._testing as tm
|
||||
from pandas.core.indexes.api import (
|
||||
Float64Index,
|
||||
Int64Index,
|
||||
)
|
||||
|
||||
|
||||
class TestAstype:
|
||||
def test_astype_float64_to_object(self):
|
||||
float_index = Float64Index([0.0, 2.5, 5.0, 7.5, 10.0])
|
||||
result = float_index.astype(object)
|
||||
assert result.equals(float_index)
|
||||
assert float_index.equals(result)
|
||||
assert isinstance(result, Index) and not isinstance(result, Float64Index)
|
||||
|
||||
def test_astype_float64_mixed_to_object(self):
|
||||
# mixed int-float
|
||||
idx = Float64Index([1.5, 2, 3, 4, 5])
|
||||
idx.name = "foo"
|
||||
result = idx.astype(object)
|
||||
assert result.equals(idx)
|
||||
assert idx.equals(result)
|
||||
assert isinstance(result, Index) and not isinstance(result, Float64Index)
|
||||
|
||||
@pytest.mark.parametrize("dtype", ["int16", "int32", "int64"])
|
||||
def test_astype_float64_to_int_dtype(self, dtype):
|
||||
# GH#12881
|
||||
# a float astype int
|
||||
idx = Float64Index([0, 1, 2])
|
||||
result = idx.astype(dtype)
|
||||
expected = Int64Index([0, 1, 2])
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
idx = Float64Index([0, 1.1, 2])
|
||||
result = idx.astype(dtype)
|
||||
expected = Int64Index([0, 1, 2])
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize("dtype", ["float32", "float64"])
|
||||
def test_astype_float64_to_float_dtype(self, dtype):
|
||||
# GH#12881
|
||||
# a float astype int
|
||||
idx = Float64Index([0, 1, 2])
|
||||
result = idx.astype(dtype)
|
||||
expected = idx
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
idx = Float64Index([0, 1.1, 2])
|
||||
result = idx.astype(dtype)
|
||||
expected = Index(idx.values.astype(dtype))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize("dtype", ["M8[ns]", "m8[ns]"])
|
||||
def test_cannot_cast_to_datetimelike(self, dtype):
|
||||
idx = Float64Index([0, 1.1, 2])
|
||||
|
||||
msg = (
|
||||
f"Cannot convert Float64Index to dtype {pandas_dtype(dtype)}; "
|
||||
f"integer values are required for conversion"
|
||||
)
|
||||
with pytest.raises(TypeError, match=re.escape(msg)):
|
||||
idx.astype(dtype)
|
||||
|
||||
@pytest.mark.parametrize("dtype", [int, "int16", "int32", "int64"])
|
||||
@pytest.mark.parametrize("non_finite", [np.inf, np.nan])
|
||||
def test_cannot_cast_inf_to_int(self, non_finite, dtype):
|
||||
# GH#13149
|
||||
idx = Float64Index([1, 2, non_finite])
|
||||
|
||||
msg = r"Cannot convert non-finite values \(NA or inf\) to integer"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.astype(dtype)
|
||||
|
||||
def test_astype_from_object(self):
|
||||
index = Index([1.0, np.nan, 0.2], dtype="object")
|
||||
result = index.astype(float)
|
||||
expected = Float64Index([1.0, np.nan, 0.2])
|
||||
assert result.dtype == expected.dtype
|
||||
tm.assert_index_equal(result, expected)
|
@ -0,0 +1,584 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas.errors import InvalidIndexError
|
||||
|
||||
from pandas import (
|
||||
Index,
|
||||
RangeIndex,
|
||||
Series,
|
||||
Timestamp,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
from pandas.core.indexes.api import (
|
||||
Float64Index,
|
||||
Int64Index,
|
||||
UInt64Index,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def index_large():
|
||||
# large values used in UInt64Index tests where no compat needed with Int64/Float64
|
||||
large = [2**63, 2**63 + 10, 2**63 + 15, 2**63 + 20, 2**63 + 25]
|
||||
return UInt64Index(large)
|
||||
|
||||
|
||||
class TestGetLoc:
|
||||
@pytest.mark.parametrize("method", [None, "pad", "backfill", "nearest"])
|
||||
def test_get_loc(self, method):
|
||||
index = Index([0, 1, 2])
|
||||
warn = None if method is None else FutureWarning
|
||||
|
||||
with tm.assert_produces_warning(warn, match="deprecated"):
|
||||
assert index.get_loc(1, method=method) == 1
|
||||
|
||||
if method:
|
||||
with tm.assert_produces_warning(warn, match="deprecated"):
|
||||
assert index.get_loc(1, method=method, tolerance=0) == 1
|
||||
|
||||
@pytest.mark.parametrize("method", [None, "pad", "backfill", "nearest"])
|
||||
@pytest.mark.filterwarnings("ignore:Passing method:FutureWarning")
|
||||
def test_get_loc_raises_bad_label(self, method):
|
||||
index = Index([0, 1, 2])
|
||||
if method:
|
||||
msg = "not supported between"
|
||||
err = TypeError
|
||||
else:
|
||||
msg = r"\[1, 2\]"
|
||||
err = InvalidIndexError
|
||||
|
||||
with pytest.raises(err, match=msg):
|
||||
index.get_loc([1, 2], method=method)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"method,loc", [("pad", 1), ("backfill", 2), ("nearest", 1)]
|
||||
)
|
||||
@pytest.mark.filterwarnings("ignore:Passing method:FutureWarning")
|
||||
def test_get_loc_tolerance(self, method, loc):
|
||||
index = Index([0, 1, 2])
|
||||
assert index.get_loc(1.1, method) == loc
|
||||
assert index.get_loc(1.1, method, tolerance=1) == loc
|
||||
|
||||
@pytest.mark.parametrize("method", ["pad", "backfill", "nearest"])
|
||||
def test_get_loc_outside_tolerance_raises(self, method):
|
||||
index = Index([0, 1, 2])
|
||||
with pytest.raises(KeyError, match="1.1"):
|
||||
with tm.assert_produces_warning(FutureWarning, match="deprecated"):
|
||||
index.get_loc(1.1, method, tolerance=0.05)
|
||||
|
||||
def test_get_loc_bad_tolerance_raises(self):
|
||||
index = Index([0, 1, 2])
|
||||
with pytest.raises(ValueError, match="must be numeric"):
|
||||
with tm.assert_produces_warning(FutureWarning, match="deprecated"):
|
||||
index.get_loc(1.1, "nearest", tolerance="invalid")
|
||||
|
||||
def test_get_loc_tolerance_no_method_raises(self):
|
||||
index = Index([0, 1, 2])
|
||||
with pytest.raises(ValueError, match="tolerance .* valid if"):
|
||||
index.get_loc(1.1, tolerance=1)
|
||||
|
||||
def test_get_loc_raises_missized_tolerance(self):
|
||||
index = Index([0, 1, 2])
|
||||
with pytest.raises(ValueError, match="tolerance size must match"):
|
||||
with tm.assert_produces_warning(FutureWarning, match="deprecated"):
|
||||
index.get_loc(1.1, "nearest", tolerance=[1, 1])
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:Passing method:FutureWarning")
|
||||
def test_get_loc_float64(self):
|
||||
idx = Float64Index([0.0, 1.0, 2.0])
|
||||
for method in [None, "pad", "backfill", "nearest"]:
|
||||
assert idx.get_loc(1, method) == 1
|
||||
if method is not None:
|
||||
assert idx.get_loc(1, method, tolerance=0) == 1
|
||||
|
||||
for method, loc in [("pad", 1), ("backfill", 2), ("nearest", 1)]:
|
||||
assert idx.get_loc(1.1, method) == loc
|
||||
assert idx.get_loc(1.1, method, tolerance=0.9) == loc
|
||||
|
||||
with pytest.raises(KeyError, match="^'foo'$"):
|
||||
idx.get_loc("foo")
|
||||
with pytest.raises(KeyError, match=r"^1\.5$"):
|
||||
idx.get_loc(1.5)
|
||||
with pytest.raises(KeyError, match=r"^1\.5$"):
|
||||
idx.get_loc(1.5, method="pad", tolerance=0.1)
|
||||
with pytest.raises(KeyError, match="^True$"):
|
||||
idx.get_loc(True)
|
||||
with pytest.raises(KeyError, match="^False$"):
|
||||
idx.get_loc(False)
|
||||
|
||||
with pytest.raises(ValueError, match="must be numeric"):
|
||||
idx.get_loc(1.4, method="nearest", tolerance="foo")
|
||||
|
||||
with pytest.raises(ValueError, match="must contain numeric elements"):
|
||||
idx.get_loc(1.4, method="nearest", tolerance=np.array(["foo"]))
|
||||
|
||||
with pytest.raises(
|
||||
ValueError, match="tolerance size must match target index size"
|
||||
):
|
||||
idx.get_loc(1.4, method="nearest", tolerance=np.array([1, 2]))
|
||||
|
||||
def test_get_loc_na(self):
|
||||
idx = Float64Index([np.nan, 1, 2])
|
||||
assert idx.get_loc(1) == 1
|
||||
assert idx.get_loc(np.nan) == 0
|
||||
|
||||
idx = Float64Index([np.nan, 1, np.nan])
|
||||
assert idx.get_loc(1) == 1
|
||||
|
||||
# representable by slice [0:2:2]
|
||||
msg = "'Cannot get left slice bound for non-unique label: nan'"
|
||||
with pytest.raises(KeyError, match=msg):
|
||||
idx.slice_locs(np.nan)
|
||||
# not representable by slice
|
||||
idx = Float64Index([np.nan, 1, np.nan, np.nan])
|
||||
assert idx.get_loc(1) == 1
|
||||
msg = "'Cannot get left slice bound for non-unique label: nan"
|
||||
with pytest.raises(KeyError, match=msg):
|
||||
idx.slice_locs(np.nan)
|
||||
|
||||
def test_get_loc_missing_nan(self):
|
||||
# GH#8569
|
||||
idx = Float64Index([1, 2])
|
||||
assert idx.get_loc(1) == 0
|
||||
with pytest.raises(KeyError, match=r"^3$"):
|
||||
idx.get_loc(3)
|
||||
with pytest.raises(KeyError, match="^nan$"):
|
||||
idx.get_loc(np.nan)
|
||||
with pytest.raises(InvalidIndexError, match=r"\[nan\]"):
|
||||
# listlike/non-hashable raises TypeError
|
||||
idx.get_loc([np.nan])
|
||||
|
||||
@pytest.mark.parametrize("vals", [[1], [1.0], [Timestamp("2019-12-31")], ["test"]])
|
||||
@pytest.mark.parametrize("method", ["nearest", "pad", "backfill"])
|
||||
def test_get_loc_float_index_nan_with_method(self, vals, method):
|
||||
# GH#39382
|
||||
idx = Index(vals)
|
||||
with pytest.raises(KeyError, match="nan"):
|
||||
with tm.assert_produces_warning(FutureWarning, match="deprecated"):
|
||||
idx.get_loc(np.nan, method=method)
|
||||
|
||||
@pytest.mark.parametrize("dtype", ["f8", "i8", "u8"])
|
||||
def test_get_loc_numericindex_none_raises(self, dtype):
|
||||
# case that goes through searchsorted and key is non-comparable to values
|
||||
arr = np.arange(10**7, dtype=dtype)
|
||||
idx = Index(arr)
|
||||
with pytest.raises(KeyError, match="None"):
|
||||
idx.get_loc(None)
|
||||
|
||||
def test_get_loc_overflows(self):
|
||||
# unique but non-monotonic goes through IndexEngine.mapping.get_item
|
||||
idx = Index([0, 2, 1])
|
||||
|
||||
val = np.iinfo(np.int64).max + 1
|
||||
|
||||
with pytest.raises(KeyError, match=str(val)):
|
||||
idx.get_loc(val)
|
||||
with pytest.raises(KeyError, match=str(val)):
|
||||
idx._engine.get_loc(val)
|
||||
|
||||
|
||||
class TestGetIndexer:
|
||||
def test_get_indexer(self):
|
||||
index1 = Index([1, 2, 3, 4, 5])
|
||||
index2 = Index([2, 4, 6])
|
||||
|
||||
r1 = index1.get_indexer(index2)
|
||||
e1 = np.array([1, 3, -1], dtype=np.intp)
|
||||
tm.assert_almost_equal(r1, e1)
|
||||
|
||||
@pytest.mark.parametrize("reverse", [True, False])
|
||||
@pytest.mark.parametrize(
|
||||
"expected,method",
|
||||
[
|
||||
(np.array([-1, 0, 0, 1, 1], dtype=np.intp), "pad"),
|
||||
(np.array([-1, 0, 0, 1, 1], dtype=np.intp), "ffill"),
|
||||
(np.array([0, 0, 1, 1, 2], dtype=np.intp), "backfill"),
|
||||
(np.array([0, 0, 1, 1, 2], dtype=np.intp), "bfill"),
|
||||
],
|
||||
)
|
||||
def test_get_indexer_methods(self, reverse, expected, method):
|
||||
index1 = Index([1, 2, 3, 4, 5])
|
||||
index2 = Index([2, 4, 6])
|
||||
|
||||
if reverse:
|
||||
index1 = index1[::-1]
|
||||
expected = expected[::-1]
|
||||
|
||||
result = index2.get_indexer(index1, method=method)
|
||||
tm.assert_almost_equal(result, expected)
|
||||
|
||||
def test_get_indexer_invalid(self):
|
||||
# GH10411
|
||||
index = Index(np.arange(10))
|
||||
|
||||
with pytest.raises(ValueError, match="tolerance argument"):
|
||||
index.get_indexer([1, 0], tolerance=1)
|
||||
|
||||
with pytest.raises(ValueError, match="limit argument"):
|
||||
index.get_indexer([1, 0], limit=1)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"method, tolerance, indexer, expected",
|
||||
[
|
||||
("pad", None, [0, 5, 9], [0, 5, 9]),
|
||||
("backfill", None, [0, 5, 9], [0, 5, 9]),
|
||||
("nearest", None, [0, 5, 9], [0, 5, 9]),
|
||||
("pad", 0, [0, 5, 9], [0, 5, 9]),
|
||||
("backfill", 0, [0, 5, 9], [0, 5, 9]),
|
||||
("nearest", 0, [0, 5, 9], [0, 5, 9]),
|
||||
("pad", None, [0.2, 1.8, 8.5], [0, 1, 8]),
|
||||
("backfill", None, [0.2, 1.8, 8.5], [1, 2, 9]),
|
||||
("nearest", None, [0.2, 1.8, 8.5], [0, 2, 9]),
|
||||
("pad", 1, [0.2, 1.8, 8.5], [0, 1, 8]),
|
||||
("backfill", 1, [0.2, 1.8, 8.5], [1, 2, 9]),
|
||||
("nearest", 1, [0.2, 1.8, 8.5], [0, 2, 9]),
|
||||
("pad", 0.2, [0.2, 1.8, 8.5], [0, -1, -1]),
|
||||
("backfill", 0.2, [0.2, 1.8, 8.5], [-1, 2, -1]),
|
||||
("nearest", 0.2, [0.2, 1.8, 8.5], [0, 2, -1]),
|
||||
],
|
||||
)
|
||||
def test_get_indexer_nearest(self, method, tolerance, indexer, expected):
|
||||
index = Index(np.arange(10))
|
||||
|
||||
actual = index.get_indexer(indexer, method=method, tolerance=tolerance)
|
||||
tm.assert_numpy_array_equal(actual, np.array(expected, dtype=np.intp))
|
||||
|
||||
@pytest.mark.parametrize("listtype", [list, tuple, Series, np.array])
|
||||
@pytest.mark.parametrize(
|
||||
"tolerance, expected",
|
||||
list(
|
||||
zip(
|
||||
[[0.3, 0.3, 0.1], [0.2, 0.1, 0.1], [0.1, 0.5, 0.5]],
|
||||
[[0, 2, -1], [0, -1, -1], [-1, 2, 9]],
|
||||
)
|
||||
),
|
||||
)
|
||||
def test_get_indexer_nearest_listlike_tolerance(
|
||||
self, tolerance, expected, listtype
|
||||
):
|
||||
index = Index(np.arange(10))
|
||||
|
||||
actual = index.get_indexer(
|
||||
[0.2, 1.8, 8.5], method="nearest", tolerance=listtype(tolerance)
|
||||
)
|
||||
tm.assert_numpy_array_equal(actual, np.array(expected, dtype=np.intp))
|
||||
|
||||
def test_get_indexer_nearest_error(self):
|
||||
index = Index(np.arange(10))
|
||||
with pytest.raises(ValueError, match="limit argument"):
|
||||
index.get_indexer([1, 0], method="nearest", limit=1)
|
||||
|
||||
with pytest.raises(ValueError, match="tolerance size must match"):
|
||||
index.get_indexer([1, 0], method="nearest", tolerance=[1, 2, 3])
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"method,expected",
|
||||
[("pad", [8, 7, 0]), ("backfill", [9, 8, 1]), ("nearest", [9, 7, 0])],
|
||||
)
|
||||
def test_get_indexer_nearest_decreasing(self, method, expected):
|
||||
index = Index(np.arange(10))[::-1]
|
||||
|
||||
actual = index.get_indexer([0, 5, 9], method=method)
|
||||
tm.assert_numpy_array_equal(actual, np.array([9, 4, 0], dtype=np.intp))
|
||||
|
||||
actual = index.get_indexer([0.2, 1.8, 8.5], method=method)
|
||||
tm.assert_numpy_array_equal(actual, np.array(expected, dtype=np.intp))
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"idx_class", [Int64Index, RangeIndex, Float64Index, UInt64Index]
|
||||
)
|
||||
@pytest.mark.parametrize("method", ["get_indexer", "get_indexer_non_unique"])
|
||||
def test_get_indexer_numeric_index_boolean_target(self, method, idx_class):
|
||||
# GH 16877
|
||||
|
||||
numeric_index = idx_class(RangeIndex(4))
|
||||
other = Index([True, False, True])
|
||||
|
||||
result = getattr(numeric_index, method)(other)
|
||||
expected = np.array([-1, -1, -1], dtype=np.intp)
|
||||
if method == "get_indexer":
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
else:
|
||||
missing = np.arange(3, dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(result[0], expected)
|
||||
tm.assert_numpy_array_equal(result[1], missing)
|
||||
|
||||
@pytest.mark.parametrize("method", ["pad", "backfill", "nearest"])
|
||||
def test_get_indexer_with_method_numeric_vs_bool(self, method):
|
||||
left = Index([1, 2, 3])
|
||||
right = Index([True, False])
|
||||
|
||||
with pytest.raises(TypeError, match="Cannot compare"):
|
||||
left.get_indexer(right, method=method)
|
||||
|
||||
with pytest.raises(TypeError, match="Cannot compare"):
|
||||
right.get_indexer(left, method=method)
|
||||
|
||||
def test_get_indexer_numeric_vs_bool(self):
|
||||
left = Index([1, 2, 3])
|
||||
right = Index([True, False])
|
||||
|
||||
res = left.get_indexer(right)
|
||||
expected = -1 * np.ones(len(right), dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(res, expected)
|
||||
|
||||
res = right.get_indexer(left)
|
||||
expected = -1 * np.ones(len(left), dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(res, expected)
|
||||
|
||||
res = left.get_indexer_non_unique(right)[0]
|
||||
expected = -1 * np.ones(len(right), dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(res, expected)
|
||||
|
||||
res = right.get_indexer_non_unique(left)[0]
|
||||
expected = -1 * np.ones(len(left), dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(res, expected)
|
||||
|
||||
def test_get_indexer_float64(self):
|
||||
idx = Float64Index([0.0, 1.0, 2.0])
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(idx), np.array([0, 1, 2], dtype=np.intp)
|
||||
)
|
||||
|
||||
target = [-0.1, 0.5, 1.1]
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "pad"), np.array([-1, 0, 1], dtype=np.intp)
|
||||
)
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "backfill"), np.array([0, 1, 2], dtype=np.intp)
|
||||
)
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "nearest"), np.array([0, 1, 1], dtype=np.intp)
|
||||
)
|
||||
|
||||
def test_get_indexer_nan(self):
|
||||
# GH#7820
|
||||
result = Float64Index([1, 2, np.nan]).get_indexer([np.nan])
|
||||
expected = np.array([2], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
def test_get_indexer_int64(self):
|
||||
index = Int64Index(range(0, 20, 2))
|
||||
target = Int64Index(np.arange(10))
|
||||
indexer = index.get_indexer(target)
|
||||
expected = np.array([0, -1, 1, -1, 2, -1, 3, -1, 4, -1], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(indexer, expected)
|
||||
|
||||
target = Int64Index(np.arange(10))
|
||||
indexer = index.get_indexer(target, method="pad")
|
||||
expected = np.array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(indexer, expected)
|
||||
|
||||
target = Int64Index(np.arange(10))
|
||||
indexer = index.get_indexer(target, method="backfill")
|
||||
expected = np.array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(indexer, expected)
|
||||
|
||||
def test_get_indexer_uint64(self, index_large):
|
||||
target = UInt64Index(np.arange(10).astype("uint64") * 5 + 2**63)
|
||||
indexer = index_large.get_indexer(target)
|
||||
expected = np.array([0, -1, 1, 2, 3, 4, -1, -1, -1, -1], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(indexer, expected)
|
||||
|
||||
target = UInt64Index(np.arange(10).astype("uint64") * 5 + 2**63)
|
||||
indexer = index_large.get_indexer(target, method="pad")
|
||||
expected = np.array([0, 0, 1, 2, 3, 4, 4, 4, 4, 4], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(indexer, expected)
|
||||
|
||||
target = UInt64Index(np.arange(10).astype("uint64") * 5 + 2**63)
|
||||
indexer = index_large.get_indexer(target, method="backfill")
|
||||
expected = np.array([0, 1, 1, 2, 3, 4, -1, -1, -1, -1], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(indexer, expected)
|
||||
|
||||
|
||||
class TestWhere:
|
||||
@pytest.mark.parametrize(
|
||||
"index",
|
||||
[
|
||||
Float64Index(np.arange(5, dtype="float64")),
|
||||
Int64Index(range(0, 20, 2)),
|
||||
UInt64Index(np.arange(5, dtype="uint64")),
|
||||
],
|
||||
)
|
||||
def test_where(self, listlike_box, index):
|
||||
cond = [True] * len(index)
|
||||
expected = index
|
||||
result = index.where(listlike_box(cond))
|
||||
|
||||
cond = [False] + [True] * (len(index) - 1)
|
||||
expected = Float64Index([index._na_value] + index[1:].tolist())
|
||||
result = index.where(listlike_box(cond))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_where_uint64(self):
|
||||
idx = UInt64Index([0, 6, 2])
|
||||
mask = np.array([False, True, False])
|
||||
other = np.array([1], dtype=np.int64)
|
||||
|
||||
expected = UInt64Index([1, 6, 1])
|
||||
|
||||
result = idx.where(mask, other)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.putmask(~mask, other)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
|
||||
class TestTake:
|
||||
@pytest.mark.parametrize("klass", [Float64Index, Int64Index, UInt64Index])
|
||||
def test_take_preserve_name(self, klass):
|
||||
index = klass([1, 2, 3, 4], name="foo")
|
||||
taken = index.take([3, 0, 1])
|
||||
assert index.name == taken.name
|
||||
|
||||
def test_take_fill_value_float64(self):
|
||||
# GH 12631
|
||||
idx = Float64Index([1.0, 2.0, 3.0], name="xxx")
|
||||
result = idx.take(np.array([1, 0, -1]))
|
||||
expected = Float64Index([2.0, 1.0, 3.0], name="xxx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# fill_value
|
||||
result = idx.take(np.array([1, 0, -1]), fill_value=True)
|
||||
expected = Float64Index([2.0, 1.0, np.nan], name="xxx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# allow_fill=False
|
||||
result = idx.take(np.array([1, 0, -1]), allow_fill=False, fill_value=True)
|
||||
expected = Float64Index([2.0, 1.0, 3.0], name="xxx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
msg = (
|
||||
"When allow_fill=True and fill_value is not None, "
|
||||
"all indices must be >= -1"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(np.array([1, 0, -2]), fill_value=True)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(np.array([1, 0, -5]), fill_value=True)
|
||||
|
||||
msg = "index -5 is out of bounds for (axis 0 with )?size 3"
|
||||
with pytest.raises(IndexError, match=msg):
|
||||
idx.take(np.array([1, -5]))
|
||||
|
||||
@pytest.mark.parametrize("klass", [Int64Index, UInt64Index])
|
||||
def test_take_fill_value_ints(self, klass):
|
||||
# see gh-12631
|
||||
idx = klass([1, 2, 3], name="xxx")
|
||||
result = idx.take(np.array([1, 0, -1]))
|
||||
expected = klass([2, 1, 3], name="xxx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
name = klass.__name__
|
||||
msg = f"Unable to fill values because {name} cannot contain NA"
|
||||
|
||||
# fill_value=True
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(np.array([1, 0, -1]), fill_value=True)
|
||||
|
||||
# allow_fill=False
|
||||
result = idx.take(np.array([1, 0, -1]), allow_fill=False, fill_value=True)
|
||||
expected = klass([2, 1, 3], name="xxx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(np.array([1, 0, -2]), fill_value=True)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(np.array([1, 0, -5]), fill_value=True)
|
||||
|
||||
msg = "index -5 is out of bounds for (axis 0 with )?size 3"
|
||||
with pytest.raises(IndexError, match=msg):
|
||||
idx.take(np.array([1, -5]))
|
||||
|
||||
|
||||
class TestContains:
|
||||
@pytest.mark.parametrize("klass", [Float64Index, Int64Index, UInt64Index])
|
||||
def test_contains_none(self, klass):
|
||||
# GH#35788 should return False, not raise TypeError
|
||||
index = klass([0, 1, 2, 3, 4])
|
||||
assert None not in index
|
||||
|
||||
def test_contains_float64_nans(self):
|
||||
index = Float64Index([1.0, 2.0, np.nan])
|
||||
assert np.nan in index
|
||||
|
||||
def test_contains_float64_not_nans(self):
|
||||
index = Float64Index([1.0, 2.0, np.nan])
|
||||
assert 1.0 in index
|
||||
|
||||
|
||||
class TestSliceLocs:
|
||||
@pytest.mark.parametrize("dtype", [int, float])
|
||||
def test_slice_locs(self, dtype):
|
||||
index = Index(np.array([0, 1, 2, 5, 6, 7, 9, 10], dtype=dtype))
|
||||
n = len(index)
|
||||
|
||||
assert index.slice_locs(start=2) == (2, n)
|
||||
assert index.slice_locs(start=3) == (3, n)
|
||||
assert index.slice_locs(3, 8) == (3, 6)
|
||||
assert index.slice_locs(5, 10) == (3, n)
|
||||
assert index.slice_locs(end=8) == (0, 6)
|
||||
assert index.slice_locs(end=9) == (0, 7)
|
||||
|
||||
# reversed
|
||||
index2 = index[::-1]
|
||||
assert index2.slice_locs(8, 2) == (2, 6)
|
||||
assert index2.slice_locs(7, 3) == (2, 5)
|
||||
|
||||
@pytest.mark.parametrize("dtype", [int, float])
|
||||
def test_slice_locs_float_locs(self, dtype):
|
||||
index = Index(np.array([0, 1, 2, 5, 6, 7, 9, 10], dtype=dtype))
|
||||
n = len(index)
|
||||
assert index.slice_locs(5.0, 10.0) == (3, n)
|
||||
assert index.slice_locs(4.5, 10.5) == (3, 8)
|
||||
|
||||
index2 = index[::-1]
|
||||
assert index2.slice_locs(8.5, 1.5) == (2, 6)
|
||||
assert index2.slice_locs(10.5, -1) == (0, n)
|
||||
|
||||
@pytest.mark.parametrize("dtype", [int, float])
|
||||
def test_slice_locs_dup_numeric(self, dtype):
|
||||
index = Index(np.array([10, 12, 12, 14], dtype=dtype))
|
||||
assert index.slice_locs(12, 12) == (1, 3)
|
||||
assert index.slice_locs(11, 13) == (1, 3)
|
||||
|
||||
index2 = index[::-1]
|
||||
assert index2.slice_locs(12, 12) == (1, 3)
|
||||
assert index2.slice_locs(13, 11) == (1, 3)
|
||||
|
||||
def test_slice_locs_na(self):
|
||||
index = Index([np.nan, 1, 2])
|
||||
assert index.slice_locs(1) == (1, 3)
|
||||
assert index.slice_locs(np.nan) == (0, 3)
|
||||
|
||||
index = Index([0, np.nan, np.nan, 1, 2])
|
||||
assert index.slice_locs(np.nan) == (1, 5)
|
||||
|
||||
def test_slice_locs_na_raises(self):
|
||||
index = Index([np.nan, 1, 2])
|
||||
with pytest.raises(KeyError, match=""):
|
||||
index.slice_locs(start=1.5)
|
||||
|
||||
with pytest.raises(KeyError, match=""):
|
||||
index.slice_locs(end=1.5)
|
||||
|
||||
|
||||
class TestGetSliceBounds:
|
||||
@pytest.mark.parametrize("kind", ["getitem", "loc", None])
|
||||
@pytest.mark.parametrize("side, expected", [("left", 4), ("right", 5)])
|
||||
def test_get_slice_bounds_within(self, kind, side, expected):
|
||||
index = Index(range(6))
|
||||
with tm.assert_produces_warning(FutureWarning, match="'kind' argument"):
|
||||
|
||||
result = index.get_slice_bound(4, kind=kind, side=side)
|
||||
assert result == expected
|
||||
|
||||
@pytest.mark.parametrize("kind", ["getitem", "loc", None])
|
||||
@pytest.mark.parametrize("side", ["left", "right"])
|
||||
@pytest.mark.parametrize("bound, expected", [(-1, 0), (10, 6)])
|
||||
def test_get_slice_bounds_outside(self, kind, side, expected, bound):
|
||||
index = Index(range(6))
|
||||
with tm.assert_produces_warning(FutureWarning, match="'kind' argument"):
|
||||
result = index.get_slice_bound(bound, kind=kind, side=side)
|
||||
assert result == expected
|
@ -0,0 +1,392 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas._testing as tm
|
||||
from pandas.core.indexes.api import (
|
||||
Index,
|
||||
Int64Index,
|
||||
UInt64Index,
|
||||
)
|
||||
|
||||
|
||||
class TestJoinInt64Index:
|
||||
def test_join_non_unique(self):
|
||||
left = Index([4, 4, 3, 3])
|
||||
|
||||
joined, lidx, ridx = left.join(left, return_indexers=True)
|
||||
|
||||
exp_joined = Index([3, 3, 3, 3, 4, 4, 4, 4])
|
||||
tm.assert_index_equal(joined, exp_joined)
|
||||
|
||||
exp_lidx = np.array([2, 2, 3, 3, 0, 0, 1, 1], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(lidx, exp_lidx)
|
||||
|
||||
exp_ridx = np.array([2, 3, 2, 3, 0, 1, 0, 1], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(ridx, exp_ridx)
|
||||
|
||||
def test_join_inner(self):
|
||||
index = Int64Index(range(0, 20, 2))
|
||||
other = Int64Index([7, 12, 25, 1, 2, 5])
|
||||
other_mono = Int64Index([1, 2, 5, 7, 12, 25])
|
||||
|
||||
# not monotonic
|
||||
res, lidx, ridx = index.join(other, how="inner", return_indexers=True)
|
||||
|
||||
# no guarantee of sortedness, so sort for comparison purposes
|
||||
ind = res.argsort()
|
||||
res = res.take(ind)
|
||||
lidx = lidx.take(ind)
|
||||
ridx = ridx.take(ind)
|
||||
|
||||
eres = Int64Index([2, 12])
|
||||
elidx = np.array([1, 6], dtype=np.intp)
|
||||
eridx = np.array([4, 1], dtype=np.intp)
|
||||
|
||||
assert isinstance(res, Int64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
# monotonic
|
||||
res, lidx, ridx = index.join(other_mono, how="inner", return_indexers=True)
|
||||
|
||||
res2 = index.intersection(other_mono)
|
||||
tm.assert_index_equal(res, res2)
|
||||
|
||||
elidx = np.array([1, 6], dtype=np.intp)
|
||||
eridx = np.array([1, 4], dtype=np.intp)
|
||||
assert isinstance(res, Int64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
def test_join_left(self):
|
||||
index = Int64Index(range(0, 20, 2))
|
||||
other = Int64Index([7, 12, 25, 1, 2, 5])
|
||||
other_mono = Int64Index([1, 2, 5, 7, 12, 25])
|
||||
|
||||
# not monotonic
|
||||
res, lidx, ridx = index.join(other, how="left", return_indexers=True)
|
||||
eres = index
|
||||
eridx = np.array([-1, 4, -1, -1, -1, -1, 1, -1, -1, -1], dtype=np.intp)
|
||||
|
||||
assert isinstance(res, Int64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
assert lidx is None
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
# monotonic
|
||||
res, lidx, ridx = index.join(other_mono, how="left", return_indexers=True)
|
||||
eridx = np.array([-1, 1, -1, -1, -1, -1, 4, -1, -1, -1], dtype=np.intp)
|
||||
assert isinstance(res, Int64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
assert lidx is None
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
# non-unique
|
||||
idx = Index([1, 1, 2, 5])
|
||||
idx2 = Index([1, 2, 5, 7, 9])
|
||||
res, lidx, ridx = idx2.join(idx, how="left", return_indexers=True)
|
||||
eres = Index([1, 1, 2, 5, 7, 9]) # 1 is in idx2, so it should be x2
|
||||
eridx = np.array([0, 1, 2, 3, -1, -1], dtype=np.intp)
|
||||
elidx = np.array([0, 0, 1, 2, 3, 4], dtype=np.intp)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
def test_join_right(self):
|
||||
index = Int64Index(range(0, 20, 2))
|
||||
other = Int64Index([7, 12, 25, 1, 2, 5])
|
||||
other_mono = Int64Index([1, 2, 5, 7, 12, 25])
|
||||
|
||||
# not monotonic
|
||||
res, lidx, ridx = index.join(other, how="right", return_indexers=True)
|
||||
eres = other
|
||||
elidx = np.array([-1, 6, -1, -1, 1, -1], dtype=np.intp)
|
||||
|
||||
assert isinstance(other, Int64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
assert ridx is None
|
||||
|
||||
# monotonic
|
||||
res, lidx, ridx = index.join(other_mono, how="right", return_indexers=True)
|
||||
eres = other_mono
|
||||
elidx = np.array([-1, 1, -1, -1, 6, -1], dtype=np.intp)
|
||||
assert isinstance(other, Int64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
assert ridx is None
|
||||
|
||||
# non-unique
|
||||
idx = Index([1, 1, 2, 5])
|
||||
idx2 = Index([1, 2, 5, 7, 9])
|
||||
res, lidx, ridx = idx.join(idx2, how="right", return_indexers=True)
|
||||
eres = Index([1, 1, 2, 5, 7, 9]) # 1 is in idx2, so it should be x2
|
||||
elidx = np.array([0, 1, 2, 3, -1, -1], dtype=np.intp)
|
||||
eridx = np.array([0, 0, 1, 2, 3, 4], dtype=np.intp)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
def test_join_non_int_index(self):
|
||||
index = Int64Index(range(0, 20, 2))
|
||||
other = Index([3, 6, 7, 8, 10], dtype=object)
|
||||
|
||||
outer = index.join(other, how="outer")
|
||||
outer2 = other.join(index, how="outer")
|
||||
expected = Index([0, 2, 3, 4, 6, 7, 8, 10, 12, 14, 16, 18])
|
||||
tm.assert_index_equal(outer, outer2)
|
||||
tm.assert_index_equal(outer, expected)
|
||||
|
||||
inner = index.join(other, how="inner")
|
||||
inner2 = other.join(index, how="inner")
|
||||
expected = Index([6, 8, 10])
|
||||
tm.assert_index_equal(inner, inner2)
|
||||
tm.assert_index_equal(inner, expected)
|
||||
|
||||
left = index.join(other, how="left")
|
||||
tm.assert_index_equal(left, index.astype(object))
|
||||
|
||||
left2 = other.join(index, how="left")
|
||||
tm.assert_index_equal(left2, other)
|
||||
|
||||
right = index.join(other, how="right")
|
||||
tm.assert_index_equal(right, other)
|
||||
|
||||
right2 = other.join(index, how="right")
|
||||
tm.assert_index_equal(right2, index.astype(object))
|
||||
|
||||
def test_join_outer(self):
|
||||
index = Int64Index(range(0, 20, 2))
|
||||
other = Int64Index([7, 12, 25, 1, 2, 5])
|
||||
other_mono = Int64Index([1, 2, 5, 7, 12, 25])
|
||||
|
||||
# not monotonic
|
||||
# guarantee of sortedness
|
||||
res, lidx, ridx = index.join(other, how="outer", return_indexers=True)
|
||||
noidx_res = index.join(other, how="outer")
|
||||
tm.assert_index_equal(res, noidx_res)
|
||||
|
||||
eres = Int64Index([0, 1, 2, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 25])
|
||||
elidx = np.array([0, -1, 1, 2, -1, 3, -1, 4, 5, 6, 7, 8, 9, -1], dtype=np.intp)
|
||||
eridx = np.array(
|
||||
[-1, 3, 4, -1, 5, -1, 0, -1, -1, 1, -1, -1, -1, 2], dtype=np.intp
|
||||
)
|
||||
|
||||
assert isinstance(res, Int64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
# monotonic
|
||||
res, lidx, ridx = index.join(other_mono, how="outer", return_indexers=True)
|
||||
noidx_res = index.join(other_mono, how="outer")
|
||||
tm.assert_index_equal(res, noidx_res)
|
||||
|
||||
elidx = np.array([0, -1, 1, 2, -1, 3, -1, 4, 5, 6, 7, 8, 9, -1], dtype=np.intp)
|
||||
eridx = np.array(
|
||||
[-1, 0, 1, -1, 2, -1, 3, -1, -1, 4, -1, -1, -1, 5], dtype=np.intp
|
||||
)
|
||||
assert isinstance(res, Int64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
|
||||
class TestJoinUInt64Index:
|
||||
@pytest.fixture
|
||||
def index_large(self):
|
||||
# large values used in TestUInt64Index where no compat needed with Int64/Float64
|
||||
large = [2**63, 2**63 + 10, 2**63 + 15, 2**63 + 20, 2**63 + 25]
|
||||
return UInt64Index(large)
|
||||
|
||||
def test_join_inner(self, index_large):
|
||||
other = UInt64Index(2**63 + np.array([7, 12, 25, 1, 2, 10], dtype="uint64"))
|
||||
other_mono = UInt64Index(
|
||||
2**63 + np.array([1, 2, 7, 10, 12, 25], dtype="uint64")
|
||||
)
|
||||
|
||||
# not monotonic
|
||||
res, lidx, ridx = index_large.join(other, how="inner", return_indexers=True)
|
||||
|
||||
# no guarantee of sortedness, so sort for comparison purposes
|
||||
ind = res.argsort()
|
||||
res = res.take(ind)
|
||||
lidx = lidx.take(ind)
|
||||
ridx = ridx.take(ind)
|
||||
|
||||
eres = UInt64Index(2**63 + np.array([10, 25], dtype="uint64"))
|
||||
elidx = np.array([1, 4], dtype=np.intp)
|
||||
eridx = np.array([5, 2], dtype=np.intp)
|
||||
|
||||
assert isinstance(res, UInt64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
# monotonic
|
||||
res, lidx, ridx = index_large.join(
|
||||
other_mono, how="inner", return_indexers=True
|
||||
)
|
||||
|
||||
res2 = index_large.intersection(other_mono)
|
||||
tm.assert_index_equal(res, res2)
|
||||
|
||||
elidx = np.array([1, 4], dtype=np.intp)
|
||||
eridx = np.array([3, 5], dtype=np.intp)
|
||||
|
||||
assert isinstance(res, UInt64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
def test_join_left(self, index_large):
|
||||
other = UInt64Index(2**63 + np.array([7, 12, 25, 1, 2, 10], dtype="uint64"))
|
||||
other_mono = UInt64Index(
|
||||
2**63 + np.array([1, 2, 7, 10, 12, 25], dtype="uint64")
|
||||
)
|
||||
|
||||
# not monotonic
|
||||
res, lidx, ridx = index_large.join(other, how="left", return_indexers=True)
|
||||
eres = index_large
|
||||
eridx = np.array([-1, 5, -1, -1, 2], dtype=np.intp)
|
||||
|
||||
assert isinstance(res, UInt64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
assert lidx is None
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
# monotonic
|
||||
res, lidx, ridx = index_large.join(other_mono, how="left", return_indexers=True)
|
||||
eridx = np.array([-1, 3, -1, -1, 5], dtype=np.intp)
|
||||
|
||||
assert isinstance(res, UInt64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
assert lidx is None
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
# non-unique
|
||||
idx = UInt64Index(2**63 + np.array([1, 1, 2, 5], dtype="uint64"))
|
||||
idx2 = UInt64Index(2**63 + np.array([1, 2, 5, 7, 9], dtype="uint64"))
|
||||
res, lidx, ridx = idx2.join(idx, how="left", return_indexers=True)
|
||||
|
||||
# 1 is in idx2, so it should be x2
|
||||
eres = UInt64Index(2**63 + np.array([1, 1, 2, 5, 7, 9], dtype="uint64"))
|
||||
eridx = np.array([0, 1, 2, 3, -1, -1], dtype=np.intp)
|
||||
elidx = np.array([0, 0, 1, 2, 3, 4], dtype=np.intp)
|
||||
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
def test_join_right(self, index_large):
|
||||
other = UInt64Index(2**63 + np.array([7, 12, 25, 1, 2, 10], dtype="uint64"))
|
||||
other_mono = UInt64Index(
|
||||
2**63 + np.array([1, 2, 7, 10, 12, 25], dtype="uint64")
|
||||
)
|
||||
|
||||
# not monotonic
|
||||
res, lidx, ridx = index_large.join(other, how="right", return_indexers=True)
|
||||
eres = other
|
||||
elidx = np.array([-1, -1, 4, -1, -1, 1], dtype=np.intp)
|
||||
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
assert isinstance(other, UInt64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
assert ridx is None
|
||||
|
||||
# monotonic
|
||||
res, lidx, ridx = index_large.join(
|
||||
other_mono, how="right", return_indexers=True
|
||||
)
|
||||
eres = other_mono
|
||||
elidx = np.array([-1, -1, -1, 1, -1, 4], dtype=np.intp)
|
||||
|
||||
assert isinstance(other, UInt64Index)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_index_equal(res, eres)
|
||||
assert ridx is None
|
||||
|
||||
# non-unique
|
||||
idx = UInt64Index(2**63 + np.array([1, 1, 2, 5], dtype="uint64"))
|
||||
idx2 = UInt64Index(2**63 + np.array([1, 2, 5, 7, 9], dtype="uint64"))
|
||||
res, lidx, ridx = idx.join(idx2, how="right", return_indexers=True)
|
||||
|
||||
# 1 is in idx2, so it should be x2
|
||||
eres = UInt64Index(2**63 + np.array([1, 1, 2, 5, 7, 9], dtype="uint64"))
|
||||
elidx = np.array([0, 1, 2, 3, -1, -1], dtype=np.intp)
|
||||
eridx = np.array([0, 0, 1, 2, 3, 4], dtype=np.intp)
|
||||
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
def test_join_non_int_index(self, index_large):
|
||||
other = Index(
|
||||
2**63 + np.array([1, 5, 7, 10, 20], dtype="uint64"), dtype=object
|
||||
)
|
||||
|
||||
outer = index_large.join(other, how="outer")
|
||||
outer2 = other.join(index_large, how="outer")
|
||||
expected = Index(
|
||||
2**63 + np.array([0, 1, 5, 7, 10, 15, 20, 25], dtype="uint64")
|
||||
)
|
||||
tm.assert_index_equal(outer, outer2)
|
||||
tm.assert_index_equal(outer, expected)
|
||||
|
||||
inner = index_large.join(other, how="inner")
|
||||
inner2 = other.join(index_large, how="inner")
|
||||
expected = Index(2**63 + np.array([10, 20], dtype="uint64"))
|
||||
tm.assert_index_equal(inner, inner2)
|
||||
tm.assert_index_equal(inner, expected)
|
||||
|
||||
left = index_large.join(other, how="left")
|
||||
tm.assert_index_equal(left, index_large.astype(object))
|
||||
|
||||
left2 = other.join(index_large, how="left")
|
||||
tm.assert_index_equal(left2, other)
|
||||
|
||||
right = index_large.join(other, how="right")
|
||||
tm.assert_index_equal(right, other)
|
||||
|
||||
right2 = other.join(index_large, how="right")
|
||||
tm.assert_index_equal(right2, index_large.astype(object))
|
||||
|
||||
def test_join_outer(self, index_large):
|
||||
other = UInt64Index(2**63 + np.array([7, 12, 25, 1, 2, 10], dtype="uint64"))
|
||||
other_mono = UInt64Index(
|
||||
2**63 + np.array([1, 2, 7, 10, 12, 25], dtype="uint64")
|
||||
)
|
||||
|
||||
# not monotonic
|
||||
# guarantee of sortedness
|
||||
res, lidx, ridx = index_large.join(other, how="outer", return_indexers=True)
|
||||
noidx_res = index_large.join(other, how="outer")
|
||||
tm.assert_index_equal(res, noidx_res)
|
||||
|
||||
eres = UInt64Index(
|
||||
2**63 + np.array([0, 1, 2, 7, 10, 12, 15, 20, 25], dtype="uint64")
|
||||
)
|
||||
elidx = np.array([0, -1, -1, -1, 1, -1, 2, 3, 4], dtype=np.intp)
|
||||
eridx = np.array([-1, 3, 4, 0, 5, 1, -1, -1, 2], dtype=np.intp)
|
||||
|
||||
assert isinstance(res, UInt64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
||||
|
||||
# monotonic
|
||||
res, lidx, ridx = index_large.join(
|
||||
other_mono, how="outer", return_indexers=True
|
||||
)
|
||||
noidx_res = index_large.join(other_mono, how="outer")
|
||||
tm.assert_index_equal(res, noidx_res)
|
||||
|
||||
elidx = np.array([0, -1, -1, -1, 1, -1, 2, 3, 4], dtype=np.intp)
|
||||
eridx = np.array([-1, 0, 1, 2, 3, 4, -1, -1, 5], dtype=np.intp)
|
||||
|
||||
assert isinstance(res, UInt64Index)
|
||||
tm.assert_index_equal(res, eres)
|
||||
tm.assert_numpy_array_equal(lidx, elidx)
|
||||
tm.assert_numpy_array_equal(ridx, eridx)
|
@ -0,0 +1,689 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs import Timestamp
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
Index,
|
||||
Series,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
from pandas.core.indexes.api import (
|
||||
Float64Index,
|
||||
Int64Index,
|
||||
NumericIndex,
|
||||
UInt64Index,
|
||||
)
|
||||
from pandas.tests.indexes.common import NumericBase
|
||||
|
||||
|
||||
class TestFloatNumericIndex(NumericBase):
|
||||
_index_cls = NumericIndex
|
||||
|
||||
@pytest.fixture(params=[np.float64, np.float32])
|
||||
def dtype(self, request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(params=["category", "datetime64", "object"])
|
||||
def invalid_dtype(self, request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture
|
||||
def simple_index(self, dtype):
|
||||
values = np.arange(5, dtype=dtype)
|
||||
return self._index_cls(values)
|
||||
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
[1.5, 2, 3, 4, 5],
|
||||
[0.0, 2.5, 5.0, 7.5, 10.0],
|
||||
[5, 4, 3, 2, 1.5],
|
||||
[10.0, 7.5, 5.0, 2.5, 0.0],
|
||||
],
|
||||
ids=["mixed", "float", "mixed_dec", "float_dec"],
|
||||
)
|
||||
def index(self, request, dtype):
|
||||
return self._index_cls(request.param, dtype=dtype)
|
||||
|
||||
@pytest.fixture
|
||||
def mixed_index(self, dtype):
|
||||
return self._index_cls([1.5, 2, 3, 4, 5], dtype=dtype)
|
||||
|
||||
@pytest.fixture
|
||||
def float_index(self, dtype):
|
||||
return self._index_cls([0.0, 2.5, 5.0, 7.5, 10.0], dtype=dtype)
|
||||
|
||||
def test_repr_roundtrip(self, index):
|
||||
tm.assert_index_equal(eval(repr(index)), index, exact=True)
|
||||
|
||||
def check_is_index(self, idx):
|
||||
assert isinstance(idx, Index)
|
||||
assert not isinstance(idx, self._index_cls)
|
||||
|
||||
def check_coerce(self, a, b, is_float_index=True):
|
||||
assert a.equals(b)
|
||||
tm.assert_index_equal(a, b, exact=False)
|
||||
if is_float_index:
|
||||
assert isinstance(b, self._index_cls)
|
||||
else:
|
||||
self.check_is_index(b)
|
||||
|
||||
def test_constructor(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
|
||||
# explicit construction
|
||||
index = index_cls([1, 2, 3, 4, 5], dtype=dtype)
|
||||
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == dtype
|
||||
|
||||
expected = np.array([1, 2, 3, 4, 5], dtype=dtype)
|
||||
tm.assert_numpy_array_equal(index.values, expected)
|
||||
|
||||
index = index_cls(np.array([1, 2, 3, 4, 5]), dtype=dtype)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == dtype
|
||||
|
||||
index = index_cls([1.0, 2, 3, 4, 5], dtype=dtype)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == dtype
|
||||
|
||||
index = index_cls(np.array([1.0, 2, 3, 4, 5]), dtype=dtype)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == dtype
|
||||
|
||||
index = index_cls([1.0, 2, 3, 4, 5], dtype=dtype)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == dtype
|
||||
|
||||
index = index_cls(np.array([1.0, 2, 3, 4, 5]), dtype=dtype)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == dtype
|
||||
|
||||
# nan handling
|
||||
result = index_cls([np.nan, np.nan], dtype=dtype)
|
||||
assert pd.isna(result.values).all()
|
||||
|
||||
result = index_cls(np.array([np.nan]), dtype=dtype)
|
||||
assert pd.isna(result.values).all()
|
||||
|
||||
def test_constructor_invalid(self):
|
||||
index_cls = self._index_cls
|
||||
cls_name = index_cls.__name__
|
||||
|
||||
# invalid
|
||||
msg = (
|
||||
rf"{cls_name}\(\.\.\.\) must be called with a collection of "
|
||||
r"some kind, 0\.0 was passed"
|
||||
)
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
index_cls(0.0)
|
||||
|
||||
# 2021-02-1 we get ValueError in numpy 1.20, but not on all builds
|
||||
msg = "|".join(
|
||||
[
|
||||
"String dtype not supported, you may need to explicitly cast ",
|
||||
"could not convert string to float: 'a'",
|
||||
]
|
||||
)
|
||||
with pytest.raises((TypeError, ValueError), match=msg):
|
||||
index_cls(["a", "b", 0.0])
|
||||
|
||||
msg = f"data is not compatible with {index_cls.__name__}"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
index_cls([Timestamp("20130101")])
|
||||
|
||||
def test_constructor_coerce(self, mixed_index, float_index):
|
||||
|
||||
self.check_coerce(mixed_index, Index([1.5, 2, 3, 4, 5]))
|
||||
self.check_coerce(float_index, Index(np.arange(5) * 2.5))
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match="will not infer"):
|
||||
result = Index(np.array(np.arange(5) * 2.5, dtype=object))
|
||||
self.check_coerce(float_index, result.astype("float64"))
|
||||
|
||||
def test_constructor_explicit(self, mixed_index, float_index):
|
||||
|
||||
# these don't auto convert
|
||||
self.check_coerce(
|
||||
float_index, Index((np.arange(5) * 2.5), dtype=object), is_float_index=False
|
||||
)
|
||||
self.check_coerce(
|
||||
mixed_index, Index([1.5, 2, 3, 4, 5], dtype=object), is_float_index=False
|
||||
)
|
||||
|
||||
def test_type_coercion_fail(self, any_int_numpy_dtype):
|
||||
# see gh-15832
|
||||
msg = "Trying to coerce float values to integers"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
Index([1, 2, 3.5], dtype=any_int_numpy_dtype)
|
||||
|
||||
def test_type_coercion_valid(self, float_numpy_dtype):
|
||||
# There is no Float32Index, so we always
|
||||
# generate Float64Index.
|
||||
idx = Index([1, 2, 3.5], dtype=float_numpy_dtype)
|
||||
tm.assert_index_equal(idx, Index([1, 2, 3.5]), exact=True)
|
||||
|
||||
def test_equals_numeric(self):
|
||||
index_cls = self._index_cls
|
||||
|
||||
idx = index_cls([1.0, 2.0])
|
||||
assert idx.equals(idx)
|
||||
assert idx.identical(idx)
|
||||
|
||||
idx2 = index_cls([1.0, 2.0])
|
||||
assert idx.equals(idx2)
|
||||
|
||||
idx = index_cls([1.0, np.nan])
|
||||
assert idx.equals(idx)
|
||||
assert idx.identical(idx)
|
||||
|
||||
idx2 = index_cls([1.0, np.nan])
|
||||
assert idx.equals(idx2)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"other",
|
||||
(
|
||||
Int64Index([1, 2]),
|
||||
Index([1.0, 2.0], dtype=object),
|
||||
Index([1, 2], dtype=object),
|
||||
),
|
||||
)
|
||||
def test_equals_numeric_other_index_type(self, other):
|
||||
idx = self._index_cls([1.0, 2.0])
|
||||
assert idx.equals(other)
|
||||
assert other.equals(idx)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"vals",
|
||||
[
|
||||
pd.date_range("2016-01-01", periods=3),
|
||||
pd.timedelta_range("1 Day", periods=3),
|
||||
],
|
||||
)
|
||||
def test_lookups_datetimelike_values(self, vals, dtype):
|
||||
|
||||
# If we have datetime64 or timedelta64 values, make sure they are
|
||||
# wrappped correctly GH#31163
|
||||
ser = Series(vals, index=range(3, 6))
|
||||
ser.index = ser.index.astype(dtype)
|
||||
|
||||
expected = vals[1]
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
result = ser.index.get_value(ser, 4.0)
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
result = ser.index.get_value(ser, 4)
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
|
||||
result = ser[4.0]
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
result = ser[4]
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
|
||||
result = ser.loc[4.0]
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
result = ser.loc[4]
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
|
||||
result = ser.at[4.0]
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
# GH#31329 .at[4] should cast to 4.0, matching .loc behavior
|
||||
result = ser.at[4]
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
|
||||
result = ser.iloc[1]
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
|
||||
result = ser.iat[1]
|
||||
assert isinstance(result, type(expected)) and result == expected
|
||||
|
||||
def test_doesnt_contain_all_the_things(self):
|
||||
idx = self._index_cls([np.nan])
|
||||
assert not idx.isin([0]).item()
|
||||
assert not idx.isin([1]).item()
|
||||
assert idx.isin([np.nan]).item()
|
||||
|
||||
def test_nan_multiple_containment(self):
|
||||
index_cls = self._index_cls
|
||||
|
||||
idx = index_cls([1.0, np.nan])
|
||||
tm.assert_numpy_array_equal(idx.isin([1.0]), np.array([True, False]))
|
||||
tm.assert_numpy_array_equal(idx.isin([2.0, np.pi]), np.array([False, False]))
|
||||
tm.assert_numpy_array_equal(idx.isin([np.nan]), np.array([False, True]))
|
||||
tm.assert_numpy_array_equal(idx.isin([1.0, np.nan]), np.array([True, True]))
|
||||
idx = index_cls([1.0, 2.0])
|
||||
tm.assert_numpy_array_equal(idx.isin([np.nan]), np.array([False, False]))
|
||||
|
||||
def test_fillna_float64(self):
|
||||
index_cls = self._index_cls
|
||||
# GH 11343
|
||||
idx = Index([1.0, np.nan, 3.0], dtype=float, name="x")
|
||||
# can't downcast
|
||||
exp = Index([1.0, 0.1, 3.0], name="x")
|
||||
tm.assert_index_equal(idx.fillna(0.1), exp, exact=True)
|
||||
|
||||
# downcast
|
||||
exact = True if index_cls is Int64Index else "equiv"
|
||||
exp = index_cls([1.0, 2.0, 3.0], name="x")
|
||||
tm.assert_index_equal(idx.fillna(2), exp, exact=exact)
|
||||
|
||||
# object
|
||||
exp = Index([1.0, "obj", 3.0], name="x")
|
||||
tm.assert_index_equal(idx.fillna("obj"), exp, exact=True)
|
||||
|
||||
|
||||
class TestFloat64Index(TestFloatNumericIndex):
|
||||
_index_cls = Float64Index
|
||||
|
||||
@pytest.fixture
|
||||
def dtype(self, request):
|
||||
return np.float64
|
||||
|
||||
@pytest.fixture(
|
||||
params=["int64", "uint64", "object", "category", "datetime64"],
|
||||
)
|
||||
def invalid_dtype(self, request):
|
||||
return request.param
|
||||
|
||||
def test_constructor_from_base_index(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
|
||||
result = Index(np.array([np.nan], dtype=dtype))
|
||||
assert isinstance(result, index_cls)
|
||||
assert result.dtype == dtype
|
||||
assert pd.isna(result.values).all()
|
||||
|
||||
def test_constructor_32bit(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
|
||||
index = index_cls(np.array([1.0, 2, 3, 4, 5]), dtype=np.float32)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == np.float64
|
||||
|
||||
index = index_cls(np.array([1, 2, 3, 4, 5]), dtype=np.float32)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == np.float64
|
||||
|
||||
|
||||
class NumericInt(NumericBase):
|
||||
def test_view(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
|
||||
idx = index_cls([], dtype=dtype, name="Foo")
|
||||
idx_view = idx.view()
|
||||
assert idx_view.name == "Foo"
|
||||
|
||||
idx_view = idx.view(dtype)
|
||||
tm.assert_index_equal(idx, index_cls(idx_view, name="Foo"), exact=True)
|
||||
|
||||
idx_view = idx.view(index_cls)
|
||||
tm.assert_index_equal(idx, index_cls(idx_view, name="Foo"), exact=True)
|
||||
|
||||
def test_is_monotonic(self):
|
||||
index_cls = self._index_cls
|
||||
|
||||
index = index_cls([1, 2, 3, 4])
|
||||
assert index.is_monotonic is True
|
||||
assert index.is_monotonic_increasing is True
|
||||
assert index._is_strictly_monotonic_increasing is True
|
||||
assert index.is_monotonic_decreasing is False
|
||||
assert index._is_strictly_monotonic_decreasing is False
|
||||
|
||||
index = index_cls([4, 3, 2, 1])
|
||||
assert index.is_monotonic is False
|
||||
assert index._is_strictly_monotonic_increasing is False
|
||||
assert index._is_strictly_monotonic_decreasing is True
|
||||
|
||||
index = index_cls([1])
|
||||
assert index.is_monotonic is True
|
||||
assert index.is_monotonic_increasing is True
|
||||
assert index.is_monotonic_decreasing is True
|
||||
assert index._is_strictly_monotonic_increasing is True
|
||||
assert index._is_strictly_monotonic_decreasing is True
|
||||
|
||||
def test_is_strictly_monotonic(self):
|
||||
index_cls = self._index_cls
|
||||
|
||||
index = index_cls([1, 1, 2, 3])
|
||||
assert index.is_monotonic_increasing is True
|
||||
assert index._is_strictly_monotonic_increasing is False
|
||||
|
||||
index = index_cls([3, 2, 1, 1])
|
||||
assert index.is_monotonic_decreasing is True
|
||||
assert index._is_strictly_monotonic_decreasing is False
|
||||
|
||||
index = index_cls([1, 1])
|
||||
assert index.is_monotonic_increasing
|
||||
assert index.is_monotonic_decreasing
|
||||
assert not index._is_strictly_monotonic_increasing
|
||||
assert not index._is_strictly_monotonic_decreasing
|
||||
|
||||
def test_logical_compat(self, simple_index):
|
||||
idx = simple_index
|
||||
assert idx.all() == idx.values.all()
|
||||
assert idx.any() == idx.values.any()
|
||||
|
||||
def test_identical(self, simple_index, dtype):
|
||||
index = simple_index
|
||||
|
||||
idx = Index(index.copy())
|
||||
assert idx.identical(index)
|
||||
|
||||
same_values_different_type = Index(idx, dtype=object)
|
||||
assert not idx.identical(same_values_different_type)
|
||||
|
||||
idx = index.astype(dtype=object)
|
||||
idx = idx.rename("foo")
|
||||
same_values = Index(idx, dtype=object)
|
||||
assert same_values.identical(idx)
|
||||
|
||||
assert not idx.identical(index)
|
||||
assert Index(same_values, name="foo", dtype=object).identical(idx)
|
||||
|
||||
assert not index.astype(dtype=object).identical(index.astype(dtype=dtype))
|
||||
|
||||
def test_cant_or_shouldnt_cast(self):
|
||||
msg = (
|
||||
"String dtype not supported, "
|
||||
"you may need to explicitly cast to a numeric type"
|
||||
)
|
||||
# can't
|
||||
data = ["foo", "bar", "baz"]
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
self._index_cls(data)
|
||||
|
||||
# shouldn't
|
||||
data = ["0", "1", "2"]
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
self._index_cls(data)
|
||||
|
||||
def test_view_index(self, simple_index):
|
||||
index = simple_index
|
||||
index.view(Index)
|
||||
|
||||
def test_prevent_casting(self, simple_index):
|
||||
index = simple_index
|
||||
result = index.astype("O")
|
||||
assert result.dtype == np.object_
|
||||
|
||||
|
||||
class TestIntNumericIndex(NumericInt):
|
||||
_index_cls = NumericIndex
|
||||
|
||||
@pytest.fixture(params=[np.int64, np.int32, np.int16, np.int8])
|
||||
def dtype(self, request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(params=["category", "datetime64", "object"])
|
||||
def invalid_dtype(self, request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture
|
||||
def simple_index(self, dtype):
|
||||
return self._index_cls(range(0, 20, 2), dtype=dtype)
|
||||
|
||||
@pytest.fixture(
|
||||
params=[range(0, 20, 2), range(19, -1, -1)], ids=["index_inc", "index_dec"]
|
||||
)
|
||||
def index(self, request, dtype):
|
||||
return self._index_cls(request.param, dtype=dtype)
|
||||
|
||||
def test_constructor(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
|
||||
# scalar raise Exception
|
||||
msg = (
|
||||
rf"{index_cls.__name__}\(\.\.\.\) must be called with a collection of some "
|
||||
"kind, 5 was passed"
|
||||
)
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
index_cls(5)
|
||||
|
||||
# copy
|
||||
# pass list, coerce fine
|
||||
index = index_cls([-5, 0, 1, 2], dtype=dtype)
|
||||
arr = index.values
|
||||
new_index = index_cls(arr, copy=True)
|
||||
tm.assert_index_equal(new_index, index, exact=True)
|
||||
val = arr[0] + 3000
|
||||
|
||||
# this should not change index
|
||||
arr[0] = val
|
||||
assert new_index[0] != val
|
||||
|
||||
if dtype == np.int64:
|
||||
exact = "equiv" if index_cls != Int64Index else True
|
||||
|
||||
# pass list, coerce fine
|
||||
index = index_cls([-5, 0, 1, 2], dtype=dtype)
|
||||
expected = Index([-5, 0, 1, 2], dtype=dtype)
|
||||
tm.assert_index_equal(index, expected, exact=exact)
|
||||
|
||||
# from iterable
|
||||
index = index_cls(iter([-5, 0, 1, 2]), dtype=dtype)
|
||||
expected = index_cls([-5, 0, 1, 2], dtype=dtype)
|
||||
tm.assert_index_equal(index, expected, exact=exact)
|
||||
|
||||
# interpret list-like
|
||||
expected = index_cls([5, 0], dtype=dtype)
|
||||
for cls in [Index, index_cls]:
|
||||
for idx in [
|
||||
cls([5, 0], dtype=dtype),
|
||||
cls(np.array([5, 0]), dtype=dtype),
|
||||
cls(Series([5, 0]), dtype=dtype),
|
||||
]:
|
||||
tm.assert_index_equal(idx, expected, exact=exact)
|
||||
|
||||
def test_constructor_corner(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
|
||||
arr = np.array([1, 2, 3, 4], dtype=object)
|
||||
|
||||
index = index_cls(arr, dtype=dtype)
|
||||
assert index.values.dtype == index.dtype
|
||||
if dtype == np.int64:
|
||||
|
||||
msg = "will not infer"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
without_dtype = Index(arr)
|
||||
|
||||
exact = True if index_cls is Int64Index else "equiv"
|
||||
tm.assert_index_equal(index, without_dtype, exact=exact)
|
||||
|
||||
# preventing casting
|
||||
arr = np.array([1, "2", 3, "4"], dtype=object)
|
||||
with pytest.raises(TypeError, match="casting"):
|
||||
index_cls(arr, dtype=dtype)
|
||||
|
||||
def test_constructor_coercion_signed_to_unsigned(
|
||||
self,
|
||||
any_unsigned_int_numpy_dtype,
|
||||
):
|
||||
|
||||
# see gh-15832
|
||||
msg = "Trying to coerce negative values to unsigned integers"
|
||||
|
||||
with pytest.raises(OverflowError, match=msg):
|
||||
Index([-1], dtype=any_unsigned_int_numpy_dtype)
|
||||
|
||||
def test_coerce_list(self):
|
||||
# coerce things
|
||||
arr = Index([1, 2, 3, 4])
|
||||
assert isinstance(arr, self._index_cls)
|
||||
|
||||
# but not if explicit dtype passed
|
||||
arr = Index([1, 2, 3, 4], dtype=object)
|
||||
assert type(arr) is Index
|
||||
|
||||
|
||||
class TestInt64Index(TestIntNumericIndex):
|
||||
_index_cls = Int64Index
|
||||
|
||||
@pytest.fixture
|
||||
def dtype(self):
|
||||
return np.int64
|
||||
|
||||
@pytest.fixture(
|
||||
params=["float64", "uint64", "object", "category", "datetime64"],
|
||||
)
|
||||
def invalid_dtype(self, request):
|
||||
return request.param
|
||||
|
||||
def test_constructor_32bit(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
|
||||
index = index_cls(np.array([1, 2, 3, 4, 5]), dtype=np.int32)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == np.int64
|
||||
|
||||
index = index_cls(np.array([1, 2, 3, 4, 5]), dtype=np.int32)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == np.int64
|
||||
|
||||
|
||||
class TestUIntNumericIndex(NumericInt):
|
||||
|
||||
_index_cls = NumericIndex
|
||||
|
||||
@pytest.fixture(params=[np.uint64])
|
||||
def dtype(self, request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(params=["category", "datetime64", "object"])
|
||||
def invalid_dtype(self, request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture
|
||||
def simple_index(self, dtype):
|
||||
# compat with shared Int64/Float64 tests
|
||||
return self._index_cls(np.arange(5, dtype=dtype))
|
||||
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
[2**63, 2**63 + 10, 2**63 + 15, 2**63 + 20, 2**63 + 25],
|
||||
[2**63 + 25, 2**63 + 20, 2**63 + 15, 2**63 + 10, 2**63],
|
||||
],
|
||||
ids=["index_inc", "index_dec"],
|
||||
)
|
||||
def index(self, request):
|
||||
return self._index_cls(request.param, dtype=np.uint64)
|
||||
|
||||
|
||||
class TestUInt64Index(TestUIntNumericIndex):
|
||||
|
||||
_index_cls = UInt64Index
|
||||
|
||||
@pytest.fixture
|
||||
def dtype(self):
|
||||
return np.uint64
|
||||
|
||||
@pytest.fixture(
|
||||
params=["int64", "float64", "object", "category", "datetime64"],
|
||||
)
|
||||
def invalid_dtype(self, request):
|
||||
return request.param
|
||||
|
||||
def test_constructor(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
exact = True if index_cls is UInt64Index else "equiv"
|
||||
|
||||
idx = index_cls([1, 2, 3])
|
||||
res = Index([1, 2, 3], dtype=dtype)
|
||||
tm.assert_index_equal(res, idx, exact=exact)
|
||||
|
||||
idx = index_cls([1, 2**63])
|
||||
res = Index([1, 2**63], dtype=dtype)
|
||||
tm.assert_index_equal(res, idx, exact=exact)
|
||||
|
||||
idx = index_cls([1, 2**63])
|
||||
res = Index([1, 2**63])
|
||||
tm.assert_index_equal(res, idx, exact=exact)
|
||||
|
||||
idx = Index([-1, 2**63], dtype=object)
|
||||
res = Index(np.array([-1, 2**63], dtype=object))
|
||||
tm.assert_index_equal(res, idx, exact=exact)
|
||||
|
||||
# https://github.com/pandas-dev/pandas/issues/29526
|
||||
idx = index_cls([1, 2**63 + 1], dtype=dtype)
|
||||
res = Index([1, 2**63 + 1], dtype=dtype)
|
||||
tm.assert_index_equal(res, idx, exact=exact)
|
||||
|
||||
def test_constructor_does_not_cast_to_float(self):
|
||||
# https://github.com/numpy/numpy/issues/19146
|
||||
values = [0, np.iinfo(np.uint64).max]
|
||||
|
||||
result = UInt64Index(values)
|
||||
assert list(result) == values
|
||||
|
||||
def test_constructor_32bit(self, dtype):
|
||||
index_cls = self._index_cls
|
||||
|
||||
index = index_cls(np.array([1, 2, 3, 4, 5]), dtype=np.uint32)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == np.uint64
|
||||
|
||||
index = index_cls(np.array([1, 2, 3, 4, 5]), dtype=np.uint32)
|
||||
assert isinstance(index, index_cls)
|
||||
assert index.dtype == np.uint64
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"box",
|
||||
[list, lambda x: np.array(x, dtype=object), lambda x: Index(x, dtype=object)],
|
||||
)
|
||||
def test_uint_index_does_not_convert_to_float64(box):
|
||||
# https://github.com/pandas-dev/pandas/issues/28279
|
||||
# https://github.com/pandas-dev/pandas/issues/28023
|
||||
series = Series(
|
||||
[0, 1, 2, 3, 4, 5],
|
||||
index=[
|
||||
7606741985629028552,
|
||||
17876870360202815256,
|
||||
17876870360202815256,
|
||||
13106359306506049338,
|
||||
8991270399732411471,
|
||||
8991270399732411472,
|
||||
],
|
||||
)
|
||||
|
||||
result = series.loc[box([7606741985629028552, 17876870360202815256])]
|
||||
|
||||
expected = UInt64Index(
|
||||
[7606741985629028552, 17876870360202815256, 17876870360202815256],
|
||||
dtype="uint64",
|
||||
)
|
||||
tm.assert_index_equal(result.index, expected)
|
||||
|
||||
tm.assert_equal(result, series[:3])
|
||||
|
||||
|
||||
def test_float64_index_equals():
|
||||
# https://github.com/pandas-dev/pandas/issues/35217
|
||||
float_index = Index([1.0, 2, 3])
|
||||
string_index = Index(["1", "2", "3"])
|
||||
|
||||
result = float_index.equals(string_index)
|
||||
assert result is False
|
||||
|
||||
result = string_index.equals(float_index)
|
||||
assert result is False
|
||||
|
||||
|
||||
def test_map_dtype_inference_unsigned_to_signed():
|
||||
# GH#44609 cases where we don't retain dtype
|
||||
idx = UInt64Index([1, 2, 3])
|
||||
result = idx.map(lambda x: -x)
|
||||
expected = Int64Index([-1, -2, -3])
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
|
||||
def test_map_dtype_inference_overflows():
|
||||
# GH#44609 case where we have to upcast
|
||||
idx = NumericIndex(np.array([1, 2, 3], dtype=np.int8))
|
||||
result = idx.map(lambda x: x * 1000)
|
||||
# TODO: we could plausibly try to infer down to int16 here
|
||||
expected = NumericIndex([1000, 2000, 3000], dtype=np.int64)
|
||||
tm.assert_index_equal(result, expected)
|
@ -0,0 +1,166 @@
|
||||
from datetime import (
|
||||
datetime,
|
||||
timedelta,
|
||||
)
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas._testing as tm
|
||||
from pandas.core.indexes.api import (
|
||||
Float64Index,
|
||||
Index,
|
||||
Int64Index,
|
||||
RangeIndex,
|
||||
UInt64Index,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def index_large():
|
||||
# large values used in TestUInt64Index where no compat needed with Int64/Float64
|
||||
large = [2**63, 2**63 + 10, 2**63 + 15, 2**63 + 20, 2**63 + 25]
|
||||
return UInt64Index(large)
|
||||
|
||||
|
||||
class TestSetOps:
|
||||
@pytest.mark.parametrize("dtype", ["f8", "u8", "i8"])
|
||||
def test_union_non_numeric(self, dtype):
|
||||
# corner case, non-numeric
|
||||
index = Index(np.arange(5, dtype=dtype), dtype=dtype)
|
||||
assert index.dtype == dtype
|
||||
|
||||
other = Index([datetime.now() + timedelta(i) for i in range(4)], dtype=object)
|
||||
result = index.union(other)
|
||||
expected = Index(np.concatenate((index, other)))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = other.union(index)
|
||||
expected = Index(np.concatenate((other, index)))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_intersection(self):
|
||||
index = Int64Index(range(5))
|
||||
|
||||
other = Index([1, 2, 3, 4, 5])
|
||||
result = index.intersection(other)
|
||||
expected = Index(np.sort(np.intersect1d(index.values, other.values)))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = other.intersection(index)
|
||||
expected = Index(
|
||||
np.sort(np.asarray(np.intersect1d(index.values, other.values)))
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize("dtype", ["int64", "uint64"])
|
||||
def test_int_float_union_dtype(self, dtype):
|
||||
# https://github.com/pandas-dev/pandas/issues/26778
|
||||
# [u]int | float -> float
|
||||
index = Index([0, 2, 3], dtype=dtype)
|
||||
other = Float64Index([0.5, 1.5])
|
||||
expected = Float64Index([0.0, 0.5, 1.5, 2.0, 3.0])
|
||||
result = index.union(other)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = other.union(index)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_range_float_union_dtype(self):
|
||||
# https://github.com/pandas-dev/pandas/issues/26778
|
||||
index = RangeIndex(start=0, stop=3)
|
||||
other = Float64Index([0.5, 1.5])
|
||||
result = index.union(other)
|
||||
expected = Float64Index([0.0, 0.5, 1, 1.5, 2.0])
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = other.union(index)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_float64_index_difference(self):
|
||||
# https://github.com/pandas-dev/pandas/issues/35217
|
||||
float_index = Index([1.0, 2, 3])
|
||||
string_index = Index(["1", "2", "3"])
|
||||
|
||||
result = float_index.difference(string_index)
|
||||
tm.assert_index_equal(result, float_index)
|
||||
|
||||
result = string_index.difference(float_index)
|
||||
tm.assert_index_equal(result, string_index)
|
||||
|
||||
def test_intersection_uint64_outside_int64_range(self, index_large):
|
||||
other = Index([2**63, 2**63 + 5, 2**63 + 10, 2**63 + 15, 2**63 + 20])
|
||||
result = index_large.intersection(other)
|
||||
expected = Index(np.sort(np.intersect1d(index_large.values, other.values)))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = other.intersection(index_large)
|
||||
expected = Index(
|
||||
np.sort(np.asarray(np.intersect1d(index_large.values, other.values)))
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"index2,keeps_name",
|
||||
[
|
||||
(Index([4, 7, 6, 5, 3], name="index"), True),
|
||||
(Index([4, 7, 6, 5, 3], name="other"), False),
|
||||
],
|
||||
)
|
||||
def test_intersection_monotonic(self, index2, keeps_name, sort):
|
||||
index1 = Index([5, 3, 2, 4, 1], name="index")
|
||||
expected = Index([5, 3, 4])
|
||||
|
||||
if keeps_name:
|
||||
expected.name = "index"
|
||||
|
||||
result = index1.intersection(index2, sort=sort)
|
||||
if sort is None:
|
||||
expected = expected.sort_values()
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_symmetric_difference(self, sort):
|
||||
# smoke
|
||||
index1 = Index([5, 2, 3, 4], name="index1")
|
||||
index2 = Index([2, 3, 4, 1])
|
||||
result = index1.symmetric_difference(index2, sort=sort)
|
||||
expected = Index([5, 1])
|
||||
assert tm.equalContents(result, expected)
|
||||
assert result.name is None
|
||||
if sort is None:
|
||||
expected = expected.sort_values()
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# __xor__ syntax
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
expected = index1 ^ index2
|
||||
assert tm.equalContents(result, expected)
|
||||
assert result.name is None
|
||||
|
||||
|
||||
class TestSetOpsSort:
|
||||
@pytest.mark.parametrize("slice_", [slice(None), slice(0)])
|
||||
def test_union_sort_other_special(self, slice_):
|
||||
# https://github.com/pandas-dev/pandas/issues/24959
|
||||
|
||||
idx = Index([1, 0, 2])
|
||||
# default, sort=None
|
||||
other = idx[slice_]
|
||||
tm.assert_index_equal(idx.union(other), idx)
|
||||
tm.assert_index_equal(other.union(idx), idx)
|
||||
|
||||
# sort=False
|
||||
tm.assert_index_equal(idx.union(other, sort=False), idx)
|
||||
|
||||
@pytest.mark.xfail(reason="Not implemented")
|
||||
@pytest.mark.parametrize("slice_", [slice(None), slice(0)])
|
||||
def test_union_sort_special_true(self, slice_):
|
||||
# TODO(GH#25151): decide on True behaviour
|
||||
# sort=True
|
||||
idx = Index([1, 0, 2])
|
||||
# default, sort=None
|
||||
other = idx[slice_]
|
||||
|
||||
result = idx.union(other, sort=True)
|
||||
expected = Index([0, 1, 2])
|
||||
tm.assert_index_equal(result, expected)
|
Reference in New Issue
Block a user