11""" define the IntervalIndex """
22
33import numpy as np
4+ import warnings
45
56from pandas .core .dtypes .missing import notna , isna
67from pandas .core .dtypes .generic import ABCDatetimeIndex , ABCPeriodIndex
@@ -151,6 +152,8 @@ class IntervalIndex(IntervalMixin, Index):
151152 Name to be stored in the index.
152153 copy : boolean, default False
153154 Copy the meta-data
155+ dtype : dtype or None, default None
156+ If None, dtype will be inferred
154157
155158 Attributes
156159 ----------
@@ -167,7 +170,6 @@ class IntervalIndex(IntervalMixin, Index):
167170 from_arrays
168171 from_tuples
169172 from_breaks
170- from_intervals
171173 contains
172174
173175 Examples
@@ -181,8 +183,7 @@ class IntervalIndex(IntervalMixin, Index):
181183
182184 It may also be constructed using one of the constructor
183185 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`.
186187
187188 See further examples in the doc strings of ``interval_range`` and the
188189 mentioned constructor methods.
@@ -211,8 +212,7 @@ class IntervalIndex(IntervalMixin, Index):
211212
212213 _mask = None
213214
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 ,
216216 fastpath = False , verify_integrity = True ):
217217
218218 if fastpath :
@@ -245,19 +245,28 @@ def __new__(cls, data, closed=None,
245245
246246 closed = closed or infer_closed
247247
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 )
250250
251251 @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 ):
254254 result = IntervalMixin .__new__ (cls )
255255
256- if closed is None :
257- closed = 'right'
256+ closed = closed or 'right'
258257 left = _ensure_index (left , copy = copy )
259258 right = _ensure_index (right , copy = copy )
260259
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+
261270 # coerce dtypes to match if needed
262271 if is_float_dtype (left ) and is_integer_dtype (right ):
263272 right = right .astype (left .dtype )
@@ -304,7 +313,7 @@ def _shallow_copy(self, left=None, right=None, **kwargs):
304313 # only single value passed, could be an IntervalIndex
305314 # or array of Intervals
306315 if not isinstance (left , IntervalIndex ):
307- left = type ( self ). from_intervals (left )
316+ left = self . _constructor (left )
308317
309318 left , right = left .left , left .right
310319 else :
@@ -322,7 +331,7 @@ def _validate(self):
322331 Verify that the IntervalIndex is valid.
323332 """
324333 if self .closed not in _VALID_CLOSED :
325- raise ValueError ("invalid options for 'closed': {closed}"
334+ raise ValueError ("invalid option for 'closed': {closed}"
326335 .format (closed = self .closed ))
327336 if len (self .left ) != len (self .right ):
328337 raise ValueError ('left and right must have the same length' )
@@ -356,7 +365,7 @@ def _engine(self):
356365
357366 @property
358367 def _constructor (self ):
359- return type (self ). from_intervals
368+ return type (self )
360369
361370 def __contains__ (self , key ):
362371 """
@@ -402,7 +411,8 @@ def contains(self, key):
402411 return False
403412
404413 @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 ):
406416 """
407417 Construct an IntervalIndex from an array of splits
408418
@@ -417,6 +427,8 @@ def from_breaks(cls, breaks, closed='right', name=None, copy=False):
417427 Name to be stored in the index.
418428 copy : boolean, default False
419429 copy the data
430+ dtype : dtype or None, default None
431+ If None, dtype will be inferred
420432
421433 Examples
422434 --------
@@ -430,18 +442,17 @@ def from_breaks(cls, breaks, closed='right', name=None, copy=False):
430442 interval_range : Function to create a fixed frequency IntervalIndex
431443 IntervalIndex.from_arrays : Construct an IntervalIndex from a left and
432444 right array
433- IntervalIndex.from_intervals : Construct an IntervalIndex from an array
434- of Interval objects
435445 IntervalIndex.from_tuples : Construct an IntervalIndex from a
436446 list/array of tuples
437447 """
438448 breaks = maybe_convert_platform_interval (breaks )
439449
440450 return cls .from_arrays (breaks [:- 1 ], breaks [1 :], closed ,
441- name = name , copy = copy )
451+ name = name , copy = copy , dtype = dtype )
442452
443453 @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 ):
445456 """
446457 Construct an IntervalIndex from a a left and right array
447458
@@ -458,6 +469,8 @@ def from_arrays(cls, left, right, closed='right', name=None, copy=False):
458469 Name to be stored in the index.
459470 copy : boolean, default False
460471 copy the data
472+ dtype : dtype or None, default None
473+ If None, dtype will be inferred
461474
462475 Examples
463476 --------
@@ -471,22 +484,23 @@ def from_arrays(cls, left, right, closed='right', name=None, copy=False):
471484 interval_range : Function to create a fixed frequency IntervalIndex
472485 IntervalIndex.from_breaks : Construct an IntervalIndex from an array of
473486 splits
474- IntervalIndex.from_intervals : Construct an IntervalIndex from an array
475- of Interval objects
476487 IntervalIndex.from_tuples : Construct an IntervalIndex from a
477488 list/array of tuples
478489 """
479490 left = maybe_convert_platform_interval (left )
480491 right = maybe_convert_platform_interval (right )
481492
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 )
484495
485496 @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 ):
487499 """
488500 Construct an IntervalIndex from a 1d array of Interval objects
489501
502+ .. deprecated:: 0.23.0
503+
490504 Parameters
491505 ----------
492506 data : array-like (1-dimensional)
@@ -496,6 +510,8 @@ def from_intervals(cls, data, name=None, copy=False):
496510 Name to be stored in the index.
497511 copy : boolean, default False
498512 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
499515
500516 Examples
501517 --------
@@ -521,16 +537,14 @@ def from_intervals(cls, data, name=None, copy=False):
521537 IntervalIndex.from_tuples : Construct an IntervalIndex from a
522538 list/array of tuples
523539 """
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 )
531544
532545 @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 ):
534548 """
535549 Construct an IntervalIndex from a list/array of tuples
536550
@@ -545,6 +559,8 @@ def from_tuples(cls, data, closed='right', name=None, copy=False):
545559 Name to be stored in the index.
546560 copy : boolean, default False
547561 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
548564
549565 Examples
550566 --------
@@ -559,8 +575,6 @@ def from_tuples(cls, data, closed='right', name=None, copy=False):
559575 right array
560576 IntervalIndex.from_breaks : Construct an IntervalIndex from an array of
561577 splits
562- IntervalIndex.from_intervals : Construct an IntervalIndex from an array
563- of Interval objects
564578 """
565579 if len (data ):
566580 left , right = [], []
@@ -571,15 +585,25 @@ def from_tuples(cls, data, closed='right', name=None, copy=False):
571585 if isna (d ):
572586 lhs = rhs = np .nan
573587 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 )
575598 left .append (lhs )
576599 right .append (rhs )
577600
578601 # TODO
579602 # if we have nulls and we previous had *only*
580603 # integer data, then we have changed the dtype
581604
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 )
583607
584608 def to_tuples (self , na_tuple = True ):
585609 """
@@ -921,7 +945,7 @@ def get_loc(self, key, method=None):
921945 Examples
922946 ---------
923947 >>> i1, i2 = pd.Interval(0, 1), pd.Interval(1, 2)
924- >>> index = pd.IntervalIndex.from_intervals ([i1, i2])
948+ >>> index = pd.IntervalIndex([i1, i2])
925949 >>> index.get_loc(1)
926950 0
927951
@@ -937,7 +961,7 @@ def get_loc(self, key, method=None):
937961 relevant intervals.
938962
939963 >>> i3 = pd.Interval(0, 2)
940- >>> overlapping_index = pd.IntervalIndex.from_intervals ([i2, i3])
964+ >>> overlapping_index = pd.IntervalIndex([i2, i3])
941965 >>> overlapping_index.get_loc(1.5)
942966 array([0, 1], dtype=int64)
943967 """
0 commit comments