6
6
from pandas import (Interval , IntervalIndex , Index , isna ,
7
7
interval_range , Timestamp , Timedelta ,
8
8
compat , date_range , timedelta_range , DateOffset )
9
- from pandas .compat import zip
9
+ from pandas .compat import lzip
10
10
from pandas .tseries .offsets import Day
11
11
from pandas ._libs .interval import IntervalTree
12
12
from pandas .tests .indexes .common import Base
@@ -38,7 +38,7 @@ def create_index_with_nan(self, closed='right'):
38
38
@pytest .mark .parametrize ('name' , [None , 'foo' ])
39
39
def test_constructors (self , closed , name ):
40
40
left , right = Index ([0 , 1 , 2 , 3 ]), Index ([1 , 2 , 3 , 4 ])
41
- ivs = [Interval (l , r , closed = closed ) for l , r in zip (left , right )]
41
+ ivs = [Interval (l , r , closed = closed ) for l , r in lzip (left , right )]
42
42
expected = IntervalIndex ._simple_new (
43
43
left = left , right = right , closed = closed , name = name )
44
44
@@ -57,7 +57,7 @@ def test_constructors(self, closed, name):
57
57
tm .assert_index_equal (result , expected )
58
58
59
59
result = IntervalIndex .from_tuples (
60
- zip (left , right ), closed = closed , name = name )
60
+ lzip (left , right ), closed = closed , name = name )
61
61
tm .assert_index_equal (result , expected )
62
62
63
63
result = Index (ivs , name = name )
@@ -68,6 +68,9 @@ def test_constructors(self, closed, name):
68
68
tm .assert_index_equal (Index (expected ), expected )
69
69
tm .assert_index_equal (IntervalIndex (expected ), expected )
70
70
71
+ result = IntervalIndex .from_intervals (expected )
72
+ tm .assert_index_equal (result , expected )
73
+
71
74
result = IntervalIndex .from_intervals (
72
75
expected .values , name = expected .name )
73
76
tm .assert_index_equal (result , expected )
@@ -86,63 +89,118 @@ def test_constructors(self, closed, name):
86
89
breaks , closed = expected .closed , name = expected .name )
87
90
tm .assert_index_equal (result , expected )
88
91
89
- def test_constructors_other (self ):
90
-
91
- # all-nan
92
- result = IntervalIndex .from_intervals ([np .nan ])
93
- expected = np .array ([np .nan ], dtype = object )
94
- tm .assert_numpy_array_equal (result .values , expected )
95
-
96
- # empty
97
- result = IntervalIndex .from_intervals ([])
98
- expected = np .array ([], dtype = object )
99
- tm .assert_numpy_array_equal (result .values , expected )
92
+ @pytest .mark .parametrize ('data' , [[np .nan ], [np .nan ] * 2 , [np .nan ] * 50 ])
93
+ def test_constructors_nan (self , closed , data ):
94
+ # GH 18421
95
+ expected_values = np .array (data , dtype = object )
96
+ expected_idx = IntervalIndex (data , closed = closed )
97
+
98
+ # validate the expected index
99
+ assert expected_idx .closed == closed
100
+ tm .assert_numpy_array_equal (expected_idx .values , expected_values )
101
+
102
+ result = IntervalIndex .from_tuples (data , closed = closed )
103
+ tm .assert_index_equal (result , expected_idx )
104
+ tm .assert_numpy_array_equal (result .values , expected_values )
105
+
106
+ result = IntervalIndex .from_breaks ([np .nan ] + data , closed = closed )
107
+ tm .assert_index_equal (result , expected_idx )
108
+ tm .assert_numpy_array_equal (result .values , expected_values )
109
+
110
+ result = IntervalIndex .from_arrays (data , data , closed = closed )
111
+ tm .assert_index_equal (result , expected_idx )
112
+ tm .assert_numpy_array_equal (result .values , expected_values )
113
+
114
+ if closed == 'right' :
115
+ # Can't specify closed for IntervalIndex.from_intervals
116
+ result = IntervalIndex .from_intervals (data )
117
+ tm .assert_index_equal (result , expected_idx )
118
+ tm .assert_numpy_array_equal (result .values , expected_values )
119
+
120
+ @pytest .mark .parametrize ('data' , [
121
+ [],
122
+ np .array ([], dtype = 'int64' ),
123
+ np .array ([], dtype = 'float64' ),
124
+ np .array ([], dtype = object )])
125
+ def test_constructors_empty (self , data , closed ):
126
+ # GH 18421
127
+ expected_dtype = data .dtype if isinstance (data , np .ndarray ) else object
128
+ expected_values = np .array ([], dtype = object )
129
+ expected_index = IntervalIndex (data , closed = closed )
130
+
131
+ # validate the expected index
132
+ assert expected_index .empty
133
+ assert expected_index .closed == closed
134
+ assert expected_index .dtype .subtype == expected_dtype
135
+ tm .assert_numpy_array_equal (expected_index .values , expected_values )
136
+
137
+ result = IntervalIndex .from_tuples (data , closed = closed )
138
+ tm .assert_index_equal (result , expected_index )
139
+ tm .assert_numpy_array_equal (result .values , expected_values )
140
+
141
+ result = IntervalIndex .from_breaks (data , closed = closed )
142
+ tm .assert_index_equal (result , expected_index )
143
+ tm .assert_numpy_array_equal (result .values , expected_values )
144
+
145
+ result = IntervalIndex .from_arrays (data , data , closed = closed )
146
+ tm .assert_index_equal (result , expected_index )
147
+ tm .assert_numpy_array_equal (result .values , expected_values )
148
+
149
+ if closed == 'right' :
150
+ # Can't specify closed for IntervalIndex.from_intervals
151
+ result = IntervalIndex .from_intervals (data )
152
+ tm .assert_index_equal (result , expected_index )
153
+ tm .assert_numpy_array_equal (result .values , expected_values )
100
154
101
155
def test_constructors_errors (self ):
102
156
103
157
# scalar
104
- msg = ('IntervalIndex(...) must be called with a collection of '
158
+ msg = ('IntervalIndex\ (...\ ) must be called with a collection of '
105
159
'some kind, 5 was passed' )
106
- with pytest . raises (TypeError , message = msg ):
160
+ with tm . assert_raises_regex (TypeError , msg ):
107
161
IntervalIndex (5 )
108
162
109
163
# not an interval
110
- msg = "type <class 'numpy.int32'> with value 0 is not an interval"
111
- with pytest .raises (TypeError , message = msg ):
164
+ msg = ("type <(class|type) 'numpy.int64'> with value 0 "
165
+ "is not an interval" )
166
+ with tm .assert_raises_regex (TypeError , msg ):
112
167
IntervalIndex ([0 , 1 ])
113
168
114
- with pytest . raises (TypeError , message = msg ):
169
+ with tm . assert_raises_regex (TypeError , msg ):
115
170
IntervalIndex .from_intervals ([0 , 1 ])
116
171
117
172
# invalid closed
118
173
msg = "invalid options for 'closed': invalid"
119
- with pytest . raises (ValueError , message = msg ):
174
+ with tm . assert_raises_regex (ValueError , msg ):
120
175
IntervalIndex .from_arrays ([0 , 1 ], [1 , 2 ], closed = 'invalid' )
121
176
122
- # mismatched closed
177
+ # mismatched closed within intervals
123
178
msg = 'intervals must all be closed on the same side'
124
- with pytest . raises (ValueError , message = msg ):
179
+ with tm . assert_raises_regex (ValueError , msg ):
125
180
IntervalIndex .from_intervals ([Interval (0 , 1 ),
126
181
Interval (1 , 2 , closed = 'left' )])
127
182
128
- with pytest .raises (ValueError , message = msg ):
129
- IntervalIndex .from_arrays ([0 , 10 ], [3 , 5 ])
130
-
131
- with pytest .raises (ValueError , message = msg ):
183
+ with tm .assert_raises_regex (ValueError , msg ):
132
184
Index ([Interval (0 , 1 ), Interval (2 , 3 , closed = 'left' )])
133
185
186
+ # mismatched closed inferred from intervals vs constructor.
187
+ msg = 'conflicting values for closed'
188
+ with tm .assert_raises_regex (ValueError , msg ):
189
+ iv = [Interval (0 , 1 , closed = 'both' ), Interval (1 , 2 , closed = 'both' )]
190
+ IntervalIndex (iv , closed = 'neither' )
191
+
134
192
# no point in nesting periods in an IntervalIndex
135
193
msg = 'Period dtypes are not supported, use a PeriodIndex instead'
136
- with pytest . raises (ValueError , message = msg ):
194
+ with tm . assert_raises_regex (ValueError , msg ):
137
195
IntervalIndex .from_breaks (
138
196
pd .period_range ('2000-01-01' , periods = 3 ))
139
197
140
198
# decreasing breaks/arrays
141
199
msg = 'left side of interval must be <= right side'
142
- with pytest . raises (ValueError , message = msg ):
200
+ with tm . assert_raises_regex (ValueError , msg ):
143
201
IntervalIndex .from_breaks (range (10 , - 1 , - 1 ))
144
202
145
- with pytest . raises (ValueError , message = msg ):
203
+ with tm . assert_raises_regex (ValueError , msg ):
146
204
IntervalIndex .from_arrays (range (10 , - 1 , - 1 ), range (9 , - 2 , - 1 ))
147
205
148
206
def test_constructors_datetimelike (self , closed ):
@@ -865,23 +923,23 @@ def test_is_non_overlapping_monotonic(self, closed):
865
923
idx = IntervalIndex .from_tuples (tpls , closed = closed )
866
924
assert idx .is_non_overlapping_monotonic is True
867
925
868
- idx = IntervalIndex .from_tuples (reversed ( tpls ) , closed = closed )
926
+ idx = IntervalIndex .from_tuples (tpls [:: - 1 ] , closed = closed )
869
927
assert idx .is_non_overlapping_monotonic is True
870
928
871
929
# Should be False in all cases (overlapping)
872
930
tpls = [(0 , 2 ), (1 , 3 ), (4 , 5 ), (6 , 7 )]
873
931
idx = IntervalIndex .from_tuples (tpls , closed = closed )
874
932
assert idx .is_non_overlapping_monotonic is False
875
933
876
- idx = IntervalIndex .from_tuples (reversed ( tpls ) , closed = closed )
934
+ idx = IntervalIndex .from_tuples (tpls [:: - 1 ] , closed = closed )
877
935
assert idx .is_non_overlapping_monotonic is False
878
936
879
937
# Should be False in all cases (non-monotonic)
880
938
tpls = [(0 , 1 ), (2 , 3 ), (6 , 7 ), (4 , 5 )]
881
939
idx = IntervalIndex .from_tuples (tpls , closed = closed )
882
940
assert idx .is_non_overlapping_monotonic is False
883
941
884
- idx = IntervalIndex .from_tuples (reversed ( tpls ) , closed = closed )
942
+ idx = IntervalIndex .from_tuples (tpls [:: - 1 ] , closed = closed )
885
943
assert idx .is_non_overlapping_monotonic is False
886
944
887
945
# Should be False for closed='both', overwise True (GH16560)
@@ -1054,10 +1112,6 @@ def test_constructor_coverage(self):
1054
1112
end = end .to_pydatetime ())
1055
1113
tm .assert_index_equal (result , expected )
1056
1114
1057
- result = pd .interval_range (start = start .tz_localize ('UTC' ),
1058
- end = end .tz_localize ('UTC' ))
1059
- tm .assert_index_equal (result , expected )
1060
-
1061
1115
result = pd .interval_range (start = start .asm8 , end = end .asm8 )
1062
1116
tm .assert_index_equal (result , expected )
1063
1117
0 commit comments