forked from pandas-dev/pandas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextension.py
149 lines (117 loc) · 4.09 KB
/
extension.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import numpy as np
from pandas._libs import index as libindex
# from pandas._libs import (lib, index as libindex, tslibs,
# algos as libalgos, join as libjoin,
# Timedelta)
from pandas.compat.numpy import function as nv
from pandas.core.arrays import ExtensionArray
from pandas.core.dtypes.common import (
ensure_platform_int,
is_integer_dtype, is_float_dtype)
from pandas.util._decorators import (
Appender, cache_readonly)
from .base import Index
# _index_doc_kwargs = dict(ibase._index_doc_kwargs)
# _index_doc_kwargs.update(
# dict(klass='IntervalIndex',
# target_klass='IntervalIndex or list of Intervals',
# name=textwrap.dedent("""\
# name : object, optional
# to be stored in the index.
# """),
# ))
class ExtensionIndex(Index):
"""
Index class that holds an ExtensionArray.
"""
_typ = 'extensionindex'
_comparables = ['name']
_attributes = ['name']
_can_hold_na = True
@property
def _is_numeric_dtype(self):
return self.dtype._is_numeric
# TODO
# # would we like our indexing holder to defer to us
# _defer_to_indexing = False
# # prioritize current class for _shallow_copy_with_infer,
# # used to infer integers as datetime-likes
# _infer_as_myclass = False
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
def __init__(self, array, name=None, copy=False, **kwargs):
# needs to accept and ignore kwargs eg for freq passed in
# Index._shallow_copy_with_infer
if isinstance(array, ExtensionIndex):
array = array._data
if not isinstance(array, ExtensionArray):
raise TypeError()
if copy:
array = array.copy()
self._data = array
self.name = name
def __len__(self):
"""
return the length of the Index
"""
return len(self._data)
@property
def size(self):
# EA does not have .size
return len(self._data)
def __array__(self, dtype=None):
""" the array interface, return my values """
return np.array(self._data)
@cache_readonly
def dtype(self):
""" return the dtype object of the underlying data """
return self._values.dtype
@cache_readonly
def dtype_str(self):
""" return the dtype str of the underlying data """
return str(self.dtype)
@property
def _values(self):
return self._data
@property
def values(self):
""" return the underlying data as an ndarray """
return self._values
@cache_readonly
def _isnan(self):
""" return if each value is nan"""
return self._values.isna()
@cache_readonly
def _engine_type(self):
values, na_value = self._values._values_for_factorize()
if is_integer_dtype(values):
return libindex.Int64Engine
elif is_float_dtype(values):
return libindex.Float64Engine
# TODO add more
else:
return libindex.ObjectEngine
@cache_readonly
def _engine(self):
# property, for now, slow to look up
values, na_value = self._values._values_for_factorize()
return self._engine_type(lambda: values, len(self))
def _format_with_header(self, header, **kwargs):
return header + list(self._format_native_types(**kwargs))
@Appender(Index.take.__doc__)
def take(self, indices, axis=0, allow_fill=True, fill_value=None,
**kwargs):
if kwargs:
nv.validate_take(tuple(), kwargs)
indices = ensure_platform_int(indices)
result = self._data.take(indices, allow_fill=allow_fill,
fill_value=fill_value)
attributes = self._get_attributes_dict()
return self._simple_new(result, **attributes)
def __getitem__(self, value):
result = self._data[value]
if isinstance(result, self._data.__class__):
return self._shallow_copy(result)
else:
# scalar
return result