Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
9739f85
ENH: Add NumIndex for indexic of any numeric type
topper-123 Apr 25, 2021
88a7858
fix various issues reported by the CI
topper-123 Apr 25, 2021
7ccb1b7
fix test failure
topper-123 Apr 26, 2021
b45500d
Make (Int|UInt|Float)64Index inherit from NumIndex
topper-123 Apr 27, 2021
5ef35f5
fix errors
topper-123 Apr 27, 2021
d8f6c22
Add more numeric tests for NumIndex
topper-123 May 2, 2021
1c65a0b
fixups
topper-123 May 2, 2021
f3e13aa
fix exact='equiv'
topper-123 May 6, 2021
4e17485
add more comprehensive tests
topper-123 May 10, 2021
c1e801d
fixes
topper-123 May 10, 2021
aa0cea7
addresses comments (move _format_native_types, assert_index_equal etc.)
topper-123 May 10, 2021
1f5f922
remove from public namespace
topper-123 May 10, 2021
132ce44
rename to NumericIndex
topper-123 May 10, 2021
058cd2e
fixes
topper-123 May 10, 2021
1c7f23f
fix test
topper-123 May 10, 2021
07a097c
ENH: Add NumIndex for indexic of any numeric type
topper-123 Apr 25, 2021
ff6cfb4
fix test failure
topper-123 Apr 26, 2021
fe7b97c
Add more numeric tests for NumIndex
topper-123 May 2, 2021
86f3960
fixups
topper-123 May 2, 2021
2424c0d
fix exact='equiv'
topper-123 May 6, 2021
a515bba
add more comprehensive tests
topper-123 May 10, 2021
341fc2f
remove from public namespace
topper-123 May 10, 2021
c2d8884
fix test
topper-123 May 10, 2021
5a56b1a
add back numeric tests
topper-123 May 11, 2021
a497d57
fix comments
topper-123 May 12, 2021
6557689
fix comments part II
topper-123 May 12, 2021
5bc4c2c
_is_num_index -> _is_numeric_index + Index.union
topper-123 May 14, 2021
84bf540
makeNumIndex -> makeNumericIndex and refactor makeIntIndex etc.
topper-123 May 14, 2021
69953b4
fix errors
topper-123 May 20, 2021
b4be77d
rebase after #41472
topper-123 May 20, 2021
bb42e2d
small clean-up
topper-123 May 20, 2021
bafa9b3
small clean-up II
topper-123 May 20, 2021
35b0e71
small clean-up III
topper-123 May 20, 2021
ed4730b
small clean-up IV
topper-123 May 20, 2021
6a32788
small clean-up V
topper-123 May 20, 2021
47e208c
fix bug
topper-123 May 20, 2021
d6a03a0
fix failures
topper-123 May 21, 2021
ec003ed
cleanups
topper-123 May 21, 2021
7ddee71
chabge _is_numeric_index to be an attribute
topper-123 May 21, 2021
2bb282f
minor clean-ups
topper-123 May 21, 2021
c1633fb
fix not-allowed parameter
topper-123 May 21, 2021
9c7d57b
fix _should_fallback_to_positional
topper-123 May 22, 2021
f6dccc1
clean-ups after rebasing
topper-123 Jun 4, 2021
3630fc7
more clean-ups
topper-123 Jun 4, 2021
bfe6895
add cleanups
topper-123 Jun 5, 2021
8532ddb
fix TestApi failure
topper-123 Jun 5, 2021
186de8e
more precise tests
topper-123 Jun 5, 2021
ead8f57
update tests
topper-123 Jun 21, 2021
2a850ea
update asserters doc string
topper-123 Jun 21, 2021
d04da70
update tests/common.py
topper-123 Jun 21, 2021
4b8385c
cleanups
topper-123 Jun 23, 2021
1f52f8b
simplify _ensure_dtype
topper-123 Jul 24, 2021
951c5f7
make attribute name clearer
topper-123 Jul 25, 2021
7c7c0dd
address comments
topper-123 Jul 28, 2021
bb72c68
add TODO
topper-123 Jul 29, 2021
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
Next Next commit
ENH: Add NumIndex for indexic of any numeric type
  • Loading branch information
topper-123 committed Jul 31, 2021
commit 9739f851600fea6f1b2de96b1b61c08a820ba95c
1 change: 1 addition & 0 deletions pandas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
UInt64Index,
RangeIndex,
Float64Index,
NumIndex,
MultiIndex,
IntervalIndex,
TimedeltaIndex,
Expand Down
3 changes: 3 additions & 0 deletions pandas/_libs/join.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ ctypedef fused join_t:
int16_t
int32_t
int64_t
uint8_t
uint16_t
uint32_t
uint64_t


Expand Down
1 change: 1 addition & 0 deletions pandas/_testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
Int64Index,
IntervalIndex,
MultiIndex,
NumIndex,
RangeIndex,
Series,
UInt64Index,
Expand Down
5 changes: 3 additions & 2 deletions pandas/_testing/asserters.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,9 @@ def assert_index_equal(
right : Index
exact : bool or {'equiv'}, default 'equiv'
Whether to check the Index class, dtype and inferred_type
are identical. If 'equiv', then RangeIndex can be substituted for
Int64Index as well.
are identical. If 'equiv', RangeIndex can be substituted for
Int64Index and signed integer dtypes will be equivalent to each other, unsigned
integer to each other and float dtypes equivalent to each other.
check_names : bool, default True
Whether to check the names attribute.
check_less_precise : bool or int, default False
Expand Down
15 changes: 14 additions & 1 deletion pandas/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,16 @@ def _create_mi_with_dt64tz_level():
"uint": tm.makeUIntIndex(100),
"range": tm.makeRangeIndex(100),
"float": tm.makeFloatIndex(100),
"num_int64": tm.makeNumIndex(100, dtype="int64"),
"num_int32": tm.makeNumIndex(100, dtype="int32"),
"num_int16": tm.makeNumIndex(100, dtype="int16"),
"num_int8": tm.makeNumIndex(100, dtype="int8"),
"num_uint64": tm.makeNumIndex(100, dtype="uint64"),
"num_uint32": tm.makeNumIndex(100, dtype="uint32"),
"num_uint16": tm.makeNumIndex(100, dtype="uint16"),
"num_uint8": tm.makeNumIndex(100, dtype="uint8"),
"num_float64": tm.makeNumIndex(100, dtype="float64"),
"num_float32": tm.makeNumIndex(100, dtype="float32"),
"bool": tm.makeBoolIndex(10),
"categorical": tm.makeCategoricalIndex(100),
"interval": tm.makeIntervalIndex(100),
Expand Down Expand Up @@ -511,7 +521,10 @@ def index_flat(request):
params=[
key
for key in indices_dict
if key not in ["int", "uint", "range", "empty", "repeats"]
if not (
key in ["int", "uint", "range", "empty", "repeats"]
or key.startswith("num_")
)
and not isinstance(indices_dict[key], MultiIndex)
]
)
Expand Down
1 change: 1 addition & 0 deletions pandas/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
Int64Index,
IntervalIndex,
MultiIndex,
NumIndex,
PeriodIndex,
RangeIndex,
TimedeltaIndex,
Expand Down
1 change: 1 addition & 0 deletions pandas/core/dtypes/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def _check(cls, inst) -> bool:
"rangeindex",
"float64index",
"uint64index",
"numindex",
"multiindex",
"datetimeindex",
"timedeltaindex",
Expand Down
2 changes: 2 additions & 0 deletions pandas/core/indexes/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
Float64Index,
Int64Index,
NumericIndex,
NumIndex,
UInt64Index,
)
from pandas.core.indexes.period import PeriodIndex
Expand All @@ -44,6 +45,7 @@
__all__ = [
"Index",
"MultiIndex",
"NumIndex",
"NumericIndex",
"Float64Index",
"Int64Index",
Expand Down
7 changes: 7 additions & 0 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ def __new__(
)

from pandas.core.arrays import PandasArray
from pandas.core.indexes.numeric import NumIndex
from pandas.core.indexes.range import RangeIndex

name = maybe_extract_name(name, data, cls)
Expand Down Expand Up @@ -436,6 +437,8 @@ def __new__(
return Index._simple_new(data, name=name)

# index-like
elif isinstance(data, NumIndex) and dtype is None:
return NumIndex(data, name=name, copy=copy)
elif isinstance(data, (np.ndarray, Index, ABCSeries)):

if isinstance(data, ABCMultiIndex):
Expand Down Expand Up @@ -5699,6 +5702,7 @@ def map(self, mapper, na_action=None):
a MultiIndex will be returned.
"""
from pandas.core.indexes.multi import MultiIndex
from pandas.core.indexes.numeric import NumIndex

new_values = self._map_values(mapper, na_action=na_action)

Expand All @@ -5719,6 +5723,9 @@ def map(self, mapper, na_action=None):
# empty
attributes["dtype"] = self.dtype

if isinstance(self, NumIndex):
return NumIndex(new_values, **attributes)

return Index(new_values, **attributes)

# TODO: De-duplicate with map, xref GH#32349
Expand Down
21 changes: 21 additions & 0 deletions pandas/core/indexes/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from pandas.core.dtypes.common import (
is_categorical_dtype,
is_scalar,
pandas_dtype,
)
from pandas.core.dtypes.missing import (
is_valid_na_for_dtype,
Expand Down Expand Up @@ -280,6 +281,26 @@ def _is_dtype_compat(self, other) -> Categorical:

return other

@doc(Index.astype)
def astype(self, dtype, copy: bool = True) -> Index:
from pandas import NumIndex

dtype = pandas_dtype(dtype)

cat = self.categories
if isinstance(cat, NumIndex):
try:
cat._validate_dtype(dtype)
except ValueError:
pass
else:
new_values = self._data.astype(dtype, copy=copy)
# pass copy=False because any copying has been done in the
# _data.astype call above
return NumIndex(new_values, name=self.name, copy=False)

return super().astype(dtype, copy=copy)

def equals(self, other: object) -> bool:
"""
Determine if two CategoricalIndex objects contain the same elements.
Expand Down
1 change: 1 addition & 0 deletions pandas/core/indexes/numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from pandas.core.dtypes.cast import astype_nansafe
from pandas.core.dtypes.common import (
is_categorical_dtype,
is_dtype_equal,
is_extension_array_dtype,
is_float,
Expand Down
6 changes: 3 additions & 3 deletions pandas/tests/indexes/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pandas.core.dtypes.dtypes import CategoricalDtype

import pandas as pd
from pandas import (
from pandas import ( # noqa
CategoricalIndex,
DatetimeIndex,
Float64Index,
Expand Down Expand Up @@ -533,7 +533,7 @@ def test_hasnans_isnans(self, index_flat):
return
elif isinstance(index, DatetimeIndexOpsMixin):
values[1] = iNaT
elif isinstance(index, (Int64Index, UInt64Index, RangeIndex)):
elif issubclass(index.dtype.type, np.integer):
return
else:
values[1] = np.nan
Expand Down Expand Up @@ -572,7 +572,7 @@ def test_fillna(self, index):

if isinstance(index, DatetimeIndexOpsMixin):
values[1] = iNaT
elif isinstance(index, (Int64Index, UInt64Index, RangeIndex)):
elif issubclass(index.dtype.type, np.integer):
return
else:
values[1] = np.nan
Expand Down
3 changes: 3 additions & 0 deletions pandas/tests/indexes/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
Float64Index,
Int64Index,
IntervalIndex,
NumIndex,
PeriodIndex,
RangeIndex,
Series,
Expand Down Expand Up @@ -713,6 +714,8 @@ def test_map_dictlike(self, index, mapper):
if index.empty:
# to match proper result coercion for uints
expected = Index([])
elif isinstance(index, NumIndex):
expected = NumIndex(np.arange(len(index), 0, -1), dtype=index.dtype)
else:
expected = Index(np.arange(len(index), 0, -1))

Expand Down
7 changes: 5 additions & 2 deletions pandas/tests/indexes/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
CategoricalIndex,
DatetimeIndex,
MultiIndex,
NumIndex,
PeriodIndex,
RangeIndex,
TimedeltaIndex,
Expand Down Expand Up @@ -261,7 +262,8 @@ def test_drop_duplicates(self, index_flat, keep):
# make unique index
holder = type(index)
unique_values = list(set(index))
unique_idx = holder(unique_values)
dtype = index.dtype if isinstance(index, NumIndex) else None
unique_idx = holder(unique_values, dtype=dtype)

# make duplicated index
n = len(unique_idx)
Expand Down Expand Up @@ -289,7 +291,8 @@ def test_drop_duplicates_no_duplicates(self, index_flat):
else:
holder = type(index)
unique_values = list(set(index))
unique_idx = holder(unique_values)
dtype = index.dtype if isinstance(index, NumIndex) else None
unique_idx = holder(unique_values, dtype=dtype)

# check on unique index
expected_duplicated = np.array([False] * len(unique_idx), dtype="bool")
Expand Down
8 changes: 3 additions & 5 deletions pandas/tests/indexes/test_numpy_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
DatetimeIndex,
Float64Index,
Index,
Int64Index,
PeriodIndex,
RangeIndex,
TimedeltaIndex,
UInt64Index,
)
import pandas._testing as tm
from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin
from pandas.core.indexes.numeric import NumericIndex


@pytest.mark.parametrize(
Expand Down Expand Up @@ -51,7 +49,7 @@ def test_numpy_ufuncs_basic(index, func):
with tm.external_error_raised((TypeError, AttributeError)):
with np.errstate(all="ignore"):
func(index)
elif isinstance(index, (Float64Index, Int64Index, UInt64Index, RangeIndex)):
elif isinstance(index, NumericIndex):
# coerces to float (e.g. np.sin)
with np.errstate(all="ignore"):
result = func(index)
Expand Down Expand Up @@ -96,7 +94,7 @@ def test_numpy_ufuncs_other(index, func, request):
with tm.external_error_raised(TypeError):
func(index)

elif isinstance(index, (Float64Index, Int64Index, UInt64Index, RangeIndex)):
elif isinstance(index, NumericIndex):
# Results in bool array
result = func(index)
assert isinstance(result, np.ndarray)
Expand Down
14 changes: 14 additions & 0 deletions pandas/tests/indexes/test_setops.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,21 @@

COMPATIBLE_INCONSISTENT_PAIRS = [
(np.float64, np.int64),
(np.float64, np.int32),
(np.float64, np.int16),
(np.float64, np.int8),
(np.float64, np.uint64),
(np.float64, np.uint32),
(np.float64, np.uint16),
(np.float64, np.uint8),
(np.float32, np.int64),
(np.float32, np.int32),
(np.float32, np.int16),
(np.float32, np.int8),
(np.float32, np.uint64),
(np.float32, np.uint32),
(np.float32, np.uint16),
(np.float32, np.uint8),
]


Expand Down