108 lines
3.5 KiB
Python
108 lines
3.5 KiB
Python
|
"""
|
||
|
The tests in this package are to ensure the proper resultant dtypes of
|
||
|
set operations.
|
||
|
"""
|
||
|
import itertools as it
|
||
|
|
||
|
import numpy as np
|
||
|
import pytest
|
||
|
|
||
|
from pandas.core.dtypes.common import is_dtype_equal
|
||
|
|
||
|
import pandas as pd
|
||
|
from pandas import Float64Index, Int64Index, RangeIndex, UInt64Index
|
||
|
import pandas._testing as tm
|
||
|
from pandas.api.types import pandas_dtype
|
||
|
from pandas.tests.indexes.conftest import indices_dict
|
||
|
|
||
|
COMPATIBLE_INCONSISTENT_PAIRS = {
|
||
|
(Int64Index, RangeIndex): (tm.makeIntIndex, tm.makeRangeIndex),
|
||
|
(Float64Index, Int64Index): (tm.makeFloatIndex, tm.makeIntIndex),
|
||
|
(Float64Index, RangeIndex): (tm.makeFloatIndex, tm.makeIntIndex),
|
||
|
(Float64Index, UInt64Index): (tm.makeFloatIndex, tm.makeUIntIndex),
|
||
|
}
|
||
|
|
||
|
|
||
|
@pytest.fixture(params=it.combinations(indices_dict, 2), ids="-".join)
|
||
|
def index_pair(request):
|
||
|
"""
|
||
|
Create all combinations of 2 index types.
|
||
|
"""
|
||
|
return indices_dict[request.param[0]], indices_dict[request.param[1]]
|
||
|
|
||
|
|
||
|
def test_union_same_types(indices):
|
||
|
# Union with a non-unique, non-monotonic index raises error
|
||
|
# Only needed for bool index factory
|
||
|
idx1 = indices.sort_values()
|
||
|
idx2 = indices.sort_values()
|
||
|
assert idx1.union(idx2).dtype == idx1.dtype
|
||
|
|
||
|
|
||
|
def test_union_different_types(index_pair):
|
||
|
# GH 23525
|
||
|
idx1, idx2 = index_pair
|
||
|
type_pair = tuple(sorted([type(idx1), type(idx2)], key=lambda x: str(x)))
|
||
|
if type_pair in COMPATIBLE_INCONSISTENT_PAIRS:
|
||
|
pytest.xfail("This test only considers non compatible indexes.")
|
||
|
|
||
|
if any(isinstance(idx, pd.MultiIndex) for idx in index_pair):
|
||
|
pytest.xfail("This test doesn't consider multiindixes.")
|
||
|
|
||
|
if is_dtype_equal(idx1.dtype, idx2.dtype):
|
||
|
pytest.xfail("This test only considers non matching dtypes.")
|
||
|
|
||
|
# A union with a CategoricalIndex (even as dtype('O')) and a
|
||
|
# non-CategoricalIndex can only be made if both indices are monotonic.
|
||
|
# This is true before this PR as well.
|
||
|
|
||
|
# Union with a non-unique, non-monotonic index raises error
|
||
|
# This applies to the boolean index
|
||
|
idx1 = idx1.sort_values()
|
||
|
idx2 = idx2.sort_values()
|
||
|
|
||
|
assert idx1.union(idx2).dtype == np.dtype("O")
|
||
|
assert idx2.union(idx1).dtype == np.dtype("O")
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize("idx_fact1,idx_fact2", COMPATIBLE_INCONSISTENT_PAIRS.values())
|
||
|
def test_compatible_inconsistent_pairs(idx_fact1, idx_fact2):
|
||
|
# GH 23525
|
||
|
idx1 = idx_fact1(10)
|
||
|
idx2 = idx_fact2(20)
|
||
|
|
||
|
res1 = idx1.union(idx2)
|
||
|
res2 = idx2.union(idx1)
|
||
|
|
||
|
assert res1.dtype in (idx1.dtype, idx2.dtype)
|
||
|
assert res2.dtype in (idx1.dtype, idx2.dtype)
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize(
|
||
|
"left, right, expected",
|
||
|
[
|
||
|
("int64", "int64", "int64"),
|
||
|
("int64", "uint64", "object"),
|
||
|
("int64", "float64", "float64"),
|
||
|
("uint64", "float64", "float64"),
|
||
|
("uint64", "uint64", "uint64"),
|
||
|
("float64", "float64", "float64"),
|
||
|
("datetime64[ns]", "int64", "object"),
|
||
|
("datetime64[ns]", "uint64", "object"),
|
||
|
("datetime64[ns]", "float64", "object"),
|
||
|
("datetime64[ns, CET]", "int64", "object"),
|
||
|
("datetime64[ns, CET]", "uint64", "object"),
|
||
|
("datetime64[ns, CET]", "float64", "object"),
|
||
|
("Period[D]", "int64", "object"),
|
||
|
("Period[D]", "uint64", "object"),
|
||
|
("Period[D]", "float64", "object"),
|
||
|
],
|
||
|
)
|
||
|
def test_union_dtypes(left, right, expected):
|
||
|
left = pandas_dtype(left)
|
||
|
right = pandas_dtype(right)
|
||
|
a = pd.Index([], dtype=left)
|
||
|
b = pd.Index([], dtype=right)
|
||
|
result = (a | b).dtype
|
||
|
assert result == expected
|