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,117 @@ 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 = getattr (data , 'dtype' , None ) or object
128
+ expected_values = np .array (data , 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 'numpy.int64 '> with value 0 is not an interval"
165
+ with tm . assert_raises_regex (TypeError , msg ):
112
166
IntervalIndex ([0 , 1 ])
113
167
114
- with pytest . raises (TypeError , message = msg ):
168
+ with tm . assert_raises_regex (TypeError , msg ):
115
169
IntervalIndex .from_intervals ([0 , 1 ])
116
170
117
171
# invalid closed
118
172
msg = "invalid options for 'closed': invalid"
119
- with pytest . raises (ValueError , message = msg ):
173
+ with tm . assert_raises_regex (ValueError , msg ):
120
174
IntervalIndex .from_arrays ([0 , 1 ], [1 , 2 ], closed = 'invalid' )
121
175
122
- # mismatched closed
176
+ # mismatched closed within intervals
123
177
msg = 'intervals must all be closed on the same side'
124
- with pytest . raises (ValueError , message = msg ):
178
+ with tm . assert_raises_regex (ValueError , msg ):
125
179
IntervalIndex .from_intervals ([Interval (0 , 1 ),
126
180
Interval (1 , 2 , closed = 'left' )])
127
181
128
- with pytest .raises (ValueError , message = msg ):
129
- IntervalIndex .from_arrays ([0 , 10 ], [3 , 5 ])
130
-
131
- with pytest .raises (ValueError , message = msg ):
182
+ with tm .assert_raises_regex (ValueError , msg ):
132
183
Index ([Interval (0 , 1 ), Interval (2 , 3 , closed = 'left' )])
133
184
185
+ # mismatched closed inferred from intervals vs constructor.
186
+ msg = 'conflicting values for closed'
187
+ with tm .assert_raises_regex (ValueError , msg ):
188
+ iv = [Interval (0 , 1 , closed = 'both' ), Interval (1 , 2 , closed = 'both' )]
189
+ IntervalIndex (iv , closed = 'neither' )
190
+
134
191
# no point in nesting periods in an IntervalIndex
135
192
msg = 'Period dtypes are not supported, use a PeriodIndex instead'
136
- with pytest . raises (ValueError , message = msg ):
193
+ with tm . assert_raises_regex (ValueError , msg ):
137
194
IntervalIndex .from_breaks (
138
195
pd .period_range ('2000-01-01' , periods = 3 ))
139
196
140
197
# decreasing breaks/arrays
141
198
msg = 'left side of interval must be <= right side'
142
- with pytest . raises (ValueError , message = msg ):
199
+ with tm . assert_raises_regex (ValueError , msg ):
143
200
IntervalIndex .from_breaks (range (10 , - 1 , - 1 ))
144
201
145
- with pytest . raises (ValueError , message = msg ):
202
+ with tm . assert_raises_regex (ValueError , msg ):
146
203
IntervalIndex .from_arrays (range (10 , - 1 , - 1 ), range (9 , - 2 , - 1 ))
147
204
148
205
def test_constructors_datetimelike (self , closed ):
@@ -865,23 +922,23 @@ def test_is_non_overlapping_monotonic(self, closed):
865
922
idx = IntervalIndex .from_tuples (tpls , closed = closed )
866
923
assert idx .is_non_overlapping_monotonic is True
867
924
868
- idx = IntervalIndex .from_tuples (reversed ( tpls ) , closed = closed )
925
+ idx = IntervalIndex .from_tuples (tpls [:: - 1 ] , closed = closed )
869
926
assert idx .is_non_overlapping_monotonic is True
870
927
871
928
# Should be False in all cases (overlapping)
872
929
tpls = [(0 , 2 ), (1 , 3 ), (4 , 5 ), (6 , 7 )]
873
930
idx = IntervalIndex .from_tuples (tpls , closed = closed )
874
931
assert idx .is_non_overlapping_monotonic is False
875
932
876
- idx = IntervalIndex .from_tuples (reversed ( tpls ) , closed = closed )
933
+ idx = IntervalIndex .from_tuples (tpls [:: - 1 ] , closed = closed )
877
934
assert idx .is_non_overlapping_monotonic is False
878
935
879
936
# Should be False in all cases (non-monotonic)
880
937
tpls = [(0 , 1 ), (2 , 3 ), (6 , 7 ), (4 , 5 )]
881
938
idx = IntervalIndex .from_tuples (tpls , closed = closed )
882
939
assert idx .is_non_overlapping_monotonic is False
883
940
884
- idx = IntervalIndex .from_tuples (reversed ( tpls ) , closed = closed )
941
+ idx = IntervalIndex .from_tuples (tpls [:: - 1 ] , closed = closed )
885
942
assert idx .is_non_overlapping_monotonic is False
886
943
887
944
# Should be False for closed='both', overwise True (GH16560)
@@ -1054,10 +1111,6 @@ def test_constructor_coverage(self):
1054
1111
end = end .to_pydatetime ())
1055
1112
tm .assert_index_equal (result , expected )
1056
1113
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
1114
result = pd .interval_range (start = start .asm8 , end = end .asm8 )
1062
1115
tm .assert_index_equal (result , expected )
1063
1116
0 commit comments