1
1
""" define the IntervalIndex """
2
2
3
3
import numpy as np
4
+ import warnings
4
5
5
6
from pandas .core .dtypes .missing import notna , isna
6
7
from pandas .core .dtypes .generic import ABCDatetimeIndex , ABCPeriodIndex
@@ -151,6 +152,8 @@ class IntervalIndex(IntervalMixin, Index):
151
152
Name to be stored in the index.
152
153
copy : boolean, default False
153
154
Copy the meta-data
155
+ dtype : dtype or None, default None
156
+ If None, dtype will be inferred
154
157
155
158
Attributes
156
159
----------
@@ -167,7 +170,6 @@ class IntervalIndex(IntervalMixin, Index):
167
170
from_arrays
168
171
from_tuples
169
172
from_breaks
170
- from_intervals
171
173
contains
172
174
173
175
Examples
@@ -181,8 +183,7 @@ class IntervalIndex(IntervalMixin, Index):
181
183
182
184
It may also be constructed using one of the constructor
183
185
methods: :meth:`IntervalIndex.from_arrays`,
184
- :meth:`IntervalIndex.from_breaks`, :meth:`IntervalIndex.from_intervals`
185
- and :meth:`IntervalIndex.from_tuples`.
186
+ :meth:`IntervalIndex.from_breaks`, and :meth:`IntervalIndex.from_tuples`.
186
187
187
188
See further examples in the doc strings of ``interval_range`` and the
188
189
mentioned constructor methods.
@@ -211,8 +212,7 @@ class IntervalIndex(IntervalMixin, Index):
211
212
212
213
_mask = None
213
214
214
- def __new__ (cls , data , closed = None ,
215
- name = None , copy = False , dtype = None ,
215
+ def __new__ (cls , data , closed = None , name = None , copy = False , dtype = None ,
216
216
fastpath = False , verify_integrity = True ):
217
217
218
218
if fastpath :
@@ -245,19 +245,28 @@ def __new__(cls, data, closed=None,
245
245
246
246
closed = closed or infer_closed
247
247
248
- return cls ._simple_new (left , right , closed , name ,
249
- copy = copy , verify_integrity = verify_integrity )
248
+ return cls ._simple_new (left , right , closed , name , copy = copy ,
249
+ dtype = dtype , verify_integrity = verify_integrity )
250
250
251
251
@classmethod
252
- def _simple_new (cls , left , right , closed = None , name = None ,
253
- copy = False , verify_integrity = True ):
252
+ def _simple_new (cls , left , right , closed = None , name = None , copy = False ,
253
+ dtype = None , verify_integrity = True ):
254
254
result = IntervalMixin .__new__ (cls )
255
255
256
- if closed is None :
257
- closed = 'right'
256
+ closed = closed or 'right'
258
257
left = _ensure_index (left , copy = copy )
259
258
right = _ensure_index (right , copy = copy )
260
259
260
+ if dtype is not None :
261
+ # GH 19262
262
+ dtype = pandas_dtype (dtype )
263
+ if not is_interval_dtype (dtype ):
264
+ msg = 'dtype must be an IntervalDtype, got {dtype}'
265
+ raise TypeError (msg .format (dtype = dtype ))
266
+ elif dtype .subtype is not None :
267
+ left = left .astype (dtype .subtype )
268
+ right = right .astype (dtype .subtype )
269
+
261
270
# coerce dtypes to match if needed
262
271
if is_float_dtype (left ) and is_integer_dtype (right ):
263
272
right = right .astype (left .dtype )
@@ -304,7 +313,7 @@ def _shallow_copy(self, left=None, right=None, **kwargs):
304
313
# only single value passed, could be an IntervalIndex
305
314
# or array of Intervals
306
315
if not isinstance (left , IntervalIndex ):
307
- left = type ( self ). from_intervals (left )
316
+ left = self . _constructor (left )
308
317
309
318
left , right = left .left , left .right
310
319
else :
@@ -322,7 +331,7 @@ def _validate(self):
322
331
Verify that the IntervalIndex is valid.
323
332
"""
324
333
if self .closed not in _VALID_CLOSED :
325
- raise ValueError ("invalid options for 'closed': {closed}"
334
+ raise ValueError ("invalid option for 'closed': {closed}"
326
335
.format (closed = self .closed ))
327
336
if len (self .left ) != len (self .right ):
328
337
raise ValueError ('left and right must have the same length' )
@@ -356,7 +365,7 @@ def _engine(self):
356
365
357
366
@property
358
367
def _constructor (self ):
359
- return type (self ). from_intervals
368
+ return type (self )
360
369
361
370
def __contains__ (self , key ):
362
371
"""
@@ -402,7 +411,8 @@ def contains(self, key):
402
411
return False
403
412
404
413
@classmethod
405
- def from_breaks (cls , breaks , closed = 'right' , name = None , copy = False ):
414
+ def from_breaks (cls , breaks , closed = 'right' , name = None , copy = False ,
415
+ dtype = None ):
406
416
"""
407
417
Construct an IntervalIndex from an array of splits
408
418
@@ -417,6 +427,8 @@ def from_breaks(cls, breaks, closed='right', name=None, copy=False):
417
427
Name to be stored in the index.
418
428
copy : boolean, default False
419
429
copy the data
430
+ dtype : dtype or None, default None
431
+ If None, dtype will be inferred
420
432
421
433
Examples
422
434
--------
@@ -430,18 +442,17 @@ def from_breaks(cls, breaks, closed='right', name=None, copy=False):
430
442
interval_range : Function to create a fixed frequency IntervalIndex
431
443
IntervalIndex.from_arrays : Construct an IntervalIndex from a left and
432
444
right array
433
- IntervalIndex.from_intervals : Construct an IntervalIndex from an array
434
- of Interval objects
435
445
IntervalIndex.from_tuples : Construct an IntervalIndex from a
436
446
list/array of tuples
437
447
"""
438
448
breaks = maybe_convert_platform_interval (breaks )
439
449
440
450
return cls .from_arrays (breaks [:- 1 ], breaks [1 :], closed ,
441
- name = name , copy = copy )
451
+ name = name , copy = copy , dtype = dtype )
442
452
443
453
@classmethod
444
- def from_arrays (cls , left , right , closed = 'right' , name = None , copy = False ):
454
+ def from_arrays (cls , left , right , closed = 'right' , name = None , copy = False ,
455
+ dtype = None ):
445
456
"""
446
457
Construct an IntervalIndex from a a left and right array
447
458
@@ -458,6 +469,8 @@ def from_arrays(cls, left, right, closed='right', name=None, copy=False):
458
469
Name to be stored in the index.
459
470
copy : boolean, default False
460
471
copy the data
472
+ dtype : dtype or None, default None
473
+ If None, dtype will be inferred
461
474
462
475
Examples
463
476
--------
@@ -471,22 +484,23 @@ def from_arrays(cls, left, right, closed='right', name=None, copy=False):
471
484
interval_range : Function to create a fixed frequency IntervalIndex
472
485
IntervalIndex.from_breaks : Construct an IntervalIndex from an array of
473
486
splits
474
- IntervalIndex.from_intervals : Construct an IntervalIndex from an array
475
- of Interval objects
476
487
IntervalIndex.from_tuples : Construct an IntervalIndex from a
477
488
list/array of tuples
478
489
"""
479
490
left = maybe_convert_platform_interval (left )
480
491
right = maybe_convert_platform_interval (right )
481
492
482
- return cls ._simple_new (left , right , closed , name = name ,
483
- copy = copy , verify_integrity = True )
493
+ return cls ._simple_new (left , right , closed , name = name , copy = copy ,
494
+ dtype = dtype , verify_integrity = True )
484
495
485
496
@classmethod
486
- def from_intervals (cls , data , name = None , copy = False ):
497
+ def from_intervals (cls , data , closed = None , name = None , copy = False ,
498
+ dtype = None ):
487
499
"""
488
500
Construct an IntervalIndex from a 1d array of Interval objects
489
501
502
+ .. deprecated:: 0.23.0
503
+
490
504
Parameters
491
505
----------
492
506
data : array-like (1-dimensional)
@@ -496,6 +510,8 @@ def from_intervals(cls, data, name=None, copy=False):
496
510
Name to be stored in the index.
497
511
copy : boolean, default False
498
512
by-default copy the data, this is compat only and ignored
513
+ dtype : dtype or None, default None
514
+ If None, dtype will be inferred
499
515
500
516
Examples
501
517
--------
@@ -521,16 +537,14 @@ def from_intervals(cls, data, name=None, copy=False):
521
537
IntervalIndex.from_tuples : Construct an IntervalIndex from a
522
538
list/array of tuples
523
539
"""
524
- if isinstance (data , IntervalIndex ):
525
- left , right , closed = data .left , data .right , data .closed
526
- name = name or data .name
527
- else :
528
- data = maybe_convert_platform_interval (data )
529
- left , right , closed = intervals_to_interval_bounds (data )
530
- return cls .from_arrays (left , right , closed , name = name , copy = False )
540
+ msg = ('IntervalIndex.from_intervals is deprecated and will be '
541
+ 'removed in a future version; use IntervalIndex(...) instead' )
542
+ warnings .warn (msg , FutureWarning , stacklevel = 2 )
543
+ return cls (data , closed = closed , name = name , copy = copy , dtype = dtype )
531
544
532
545
@classmethod
533
- def from_tuples (cls , data , closed = 'right' , name = None , copy = False ):
546
+ def from_tuples (cls , data , closed = 'right' , name = None , copy = False ,
547
+ dtype = None ):
534
548
"""
535
549
Construct an IntervalIndex from a list/array of tuples
536
550
@@ -545,6 +559,8 @@ def from_tuples(cls, data, closed='right', name=None, copy=False):
545
559
Name to be stored in the index.
546
560
copy : boolean, default False
547
561
by-default copy the data, this is compat only and ignored
562
+ dtype : dtype or None, default None
563
+ If None, dtype will be inferred
548
564
549
565
Examples
550
566
--------
@@ -559,8 +575,6 @@ def from_tuples(cls, data, closed='right', name=None, copy=False):
559
575
right array
560
576
IntervalIndex.from_breaks : Construct an IntervalIndex from an array of
561
577
splits
562
- IntervalIndex.from_intervals : Construct an IntervalIndex from an array
563
- of Interval objects
564
578
"""
565
579
if len (data ):
566
580
left , right = [], []
@@ -571,15 +585,25 @@ def from_tuples(cls, data, closed='right', name=None, copy=False):
571
585
if isna (d ):
572
586
lhs = rhs = np .nan
573
587
else :
574
- lhs , rhs = d
588
+ try :
589
+ lhs , rhs = d
590
+ except ValueError :
591
+ msg = ('IntervalIndex.from_tuples requires tuples of '
592
+ 'length 2, got {tpl}' ).format (tpl = d )
593
+ raise ValueError (msg )
594
+ except TypeError :
595
+ msg = ('IntervalIndex.from_tuples received an invalid '
596
+ 'item, {tpl}' ).format (tpl = d )
597
+ raise TypeError (msg )
575
598
left .append (lhs )
576
599
right .append (rhs )
577
600
578
601
# TODO
579
602
# if we have nulls and we previous had *only*
580
603
# integer data, then we have changed the dtype
581
604
582
- return cls .from_arrays (left , right , closed , name = name , copy = False )
605
+ return cls .from_arrays (left , right , closed , name = name , copy = False ,
606
+ dtype = dtype )
583
607
584
608
def to_tuples (self , na_tuple = True ):
585
609
"""
@@ -921,7 +945,7 @@ def get_loc(self, key, method=None):
921
945
Examples
922
946
---------
923
947
>>> i1, i2 = pd.Interval(0, 1), pd.Interval(1, 2)
924
- >>> index = pd.IntervalIndex.from_intervals ([i1, i2])
948
+ >>> index = pd.IntervalIndex([i1, i2])
925
949
>>> index.get_loc(1)
926
950
0
927
951
@@ -937,7 +961,7 @@ def get_loc(self, key, method=None):
937
961
relevant intervals.
938
962
939
963
>>> i3 = pd.Interval(0, 2)
940
- >>> overlapping_index = pd.IntervalIndex.from_intervals ([i2, i3])
964
+ >>> overlapping_index = pd.IntervalIndex([i2, i3])
941
965
>>> overlapping_index.get_loc(1.5)
942
966
array([0, 1], dtype=int64)
943
967
"""
0 commit comments