17
17
is_period_dtype ,
18
18
is_bool_dtype ,
19
19
pandas_dtype ,
20
- _ensure_int64 ,
21
20
_ensure_object )
22
21
from pandas .types .dtypes import PeriodDtype
23
22
from pandas .types .generic import ABCSeries
@@ -215,11 +214,46 @@ def __new__(cls, data=None, ordinal=None, freq=None, start=None, end=None,
215
214
else :
216
215
data , freq = cls ._generate_range (start , end , periods ,
217
216
freq , kwargs )
218
- else :
219
- ordinal , freq = cls ._from_arraylike (data , freq , tz )
220
- data = np .array (ordinal , dtype = np .int64 , copy = copy )
217
+ return cls ._from_ordinals (data , name = name , freq = freq )
218
+
219
+ if isinstance (data , PeriodIndex ):
220
+ if freq is None or freq == data .freq :
221
+ freq = data .freq
222
+ data = data ._values
223
+ else :
224
+ base1 , _ = _gfc (data .freq )
225
+ base2 , _ = _gfc (freq )
226
+ data = period .period_asfreq_arr (data ._values ,
227
+ base1 , base2 , 1 )
228
+ return cls ._simple_new (data , name = name , freq = freq )
221
229
222
- return cls ._simple_new (data , name = name , freq = freq )
230
+ if not isinstance (data , (np .ndarray , PeriodIndex ,
231
+ DatetimeIndex , Int64Index )):
232
+ if is_scalar (data ) or isinstance (data , Period ):
233
+ raise ValueError ('PeriodIndex() must be called with a '
234
+ 'collection of some kind, %s was passed'
235
+ % repr (data ))
236
+
237
+ # other iterable of some kind
238
+ if not isinstance (data , (list , tuple )):
239
+ data = list (data )
240
+
241
+ data = np .asarray (data )
242
+
243
+ if np .issubdtype (data .dtype , np .datetime64 ):
244
+ data = dt64arr_to_periodarr (data , freq , tz )
245
+ return cls ._from_ordinals (data , name = name , freq = freq )
246
+
247
+ inferred_dtype = infer_dtype (data )
248
+
249
+ if inferred_dtype == 'floating' and len (data ) > 0 :
250
+ raise TypeError ("PeriodIndex can't take floats" )
251
+
252
+ else :
253
+ data = _ensure_object (data )
254
+ freq = freq or period .extract_freq (data )
255
+ data = period .extract_ordinals (data , freq )
256
+ return cls ._from_ordinals (data , name = name , freq = freq )
223
257
224
258
@classmethod
225
259
def _generate_range (cls , start , end , periods , freq , fields ):
@@ -240,68 +274,6 @@ def _generate_range(cls, start, end, periods, freq, fields):
240
274
241
275
return subarr , freq
242
276
243
- @classmethod
244
- def _from_arraylike (cls , data , freq , tz ):
245
- if freq is not None :
246
- freq = Period ._maybe_convert_freq (freq )
247
-
248
- if not isinstance (data , (np .ndarray , PeriodIndex ,
249
- DatetimeIndex , Int64Index )):
250
- if is_scalar (data ) or isinstance (data , Period ):
251
- raise ValueError ('PeriodIndex() must be called with a '
252
- 'collection of some kind, %s was passed'
253
- % repr (data ))
254
-
255
- # other iterable of some kind
256
- if not isinstance (data , (list , tuple )):
257
- data = list (data )
258
-
259
- try :
260
- data = _ensure_int64 (data )
261
- if freq is None :
262
- raise ValueError ('freq not specified' )
263
- data = np .array ([Period (x , freq = freq ) for x in data ],
264
- dtype = np .int64 )
265
- except (TypeError , ValueError ):
266
- data = _ensure_object (data )
267
-
268
- if freq is None :
269
- freq = period .extract_freq (data )
270
- data = period .extract_ordinals (data , freq )
271
- else :
272
- if isinstance (data , PeriodIndex ):
273
- if freq is None or freq == data .freq :
274
- freq = data .freq
275
- data = data ._values
276
- else :
277
- base1 , _ = _gfc (data .freq )
278
- base2 , _ = _gfc (freq )
279
- data = period .period_asfreq_arr (data ._values ,
280
- base1 , base2 , 1 )
281
- else :
282
- if is_object_dtype (data ):
283
- inferred = infer_dtype (data )
284
- if inferred == 'integer' :
285
- data = data .astype (np .int64 )
286
-
287
- if freq is None and is_object_dtype (data ):
288
- # must contain Period instance and thus extract ordinals
289
- freq = period .extract_freq (data )
290
- data = period .extract_ordinals (data , freq )
291
-
292
- if freq is None :
293
- msg = 'freq not specified and cannot be inferred'
294
- raise ValueError (msg )
295
-
296
- if data .dtype != np .int64 :
297
- if np .issubdtype (data .dtype , np .datetime64 ):
298
- data = dt64arr_to_periodarr (data , freq , tz )
299
- else :
300
- data = _ensure_object (data )
301
- data = period .extract_ordinals (data , freq )
302
-
303
- return data , freq
304
-
305
277
@classmethod
306
278
def _simple_new (cls , values , name = None , freq = None , ** kwargs ):
307
279
@@ -312,13 +284,18 @@ def _simple_new(cls, values, name=None, freq=None, **kwargs):
312
284
else :
313
285
return cls (values , name = name , freq = freq , ** kwargs )
314
286
287
+ return cls ._from_ordinals (values , name , freq , ** kwargs )
288
+
289
+ @classmethod
290
+ def _from_ordinals (cls , values , name = None , freq = None , ** kwargs ):
291
+
315
292
values = np .array (values , dtype = 'int64' , copy = False )
316
293
317
294
result = object .__new__ (cls )
318
295
result ._data = values
319
296
result .name = name
320
297
if freq is None :
321
- raise ValueError ('freq is not specified' )
298
+ raise ValueError ('freq is not specified and cannot be inferred ' )
322
299
result .freq = Period ._maybe_convert_freq (freq )
323
300
result ._reset_identity ()
324
301
return result
@@ -329,7 +306,6 @@ def _shallow_copy_with_infer(self, values=None, **kwargs):
329
306
330
307
def _shallow_copy (self , values = None , ** kwargs ):
331
308
if kwargs .get ('freq' ) is None :
332
- # freq must be provided
333
309
kwargs ['freq' ] = self .freq
334
310
if values is None :
335
311
values = self ._values
@@ -413,7 +389,7 @@ def __array_wrap__(self, result, context=None):
413
389
return result
414
390
# the result is object dtype array of Period
415
391
# cannot pass _simple_new as it is
416
- return PeriodIndex (result , freq = self .freq , name = self .name )
392
+ return self . _shallow_copy (result , freq = self .freq , name = self .name )
417
393
418
394
@property
419
395
def _box_func (self ):
@@ -708,7 +684,7 @@ def shift(self, n):
708
684
values = self ._values + n * self .freq .n
709
685
if self .hasnans :
710
686
values [self ._isnan ] = tslib .iNaT
711
- return PeriodIndex ( data = values , name = self . name , freq = self . freq )
687
+ return self . _shallow_copy ( values = values )
712
688
713
689
@cache_readonly
714
690
def dtype (self ):
@@ -945,7 +921,8 @@ def _wrap_union_result(self, other, result):
945
921
946
922
def _apply_meta (self , rawarr ):
947
923
if not isinstance (rawarr , PeriodIndex ):
948
- rawarr = PeriodIndex (rawarr , freq = self .freq )
924
+ rawarr = PeriodIndex ._from_ordinals (rawarr , freq = self .freq ,
925
+ name = self .name )
949
926
return rawarr
950
927
951
928
def _format_native_types (self , na_rep = u ('NaT' ), date_format = None ,
0 commit comments