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
@@ -211,11 +210,46 @@ def __new__(cls, data=None, ordinal=None, freq=None, start=None, end=None,
211
210
else :
212
211
data , freq = cls ._generate_range (start , end , periods ,
213
212
freq , kwargs )
214
- else :
215
- ordinal , freq = cls ._from_arraylike (data , freq , tz )
216
- data = np .array (ordinal , dtype = np .int64 , copy = copy )
213
+ return cls ._from_ordinals (data , name = name , freq = freq )
214
+
215
+ if isinstance (data , PeriodIndex ):
216
+ if freq is None or freq == data .freq :
217
+ freq = data .freq
218
+ data = data ._values
219
+ else :
220
+ base1 , _ = _gfc (data .freq )
221
+ base2 , _ = _gfc (freq )
222
+ data = period .period_asfreq_arr (data ._values ,
223
+ base1 , base2 , 1 )
224
+ return cls ._simple_new (data , name = name , freq = freq )
217
225
218
- return cls ._simple_new (data , name = name , freq = freq )
226
+ if not isinstance (data , (np .ndarray , PeriodIndex ,
227
+ DatetimeIndex , Int64Index )):
228
+ if is_scalar (data ) or isinstance (data , Period ):
229
+ raise ValueError ('PeriodIndex() must be called with a '
230
+ 'collection of some kind, %s was passed'
231
+ % repr (data ))
232
+
233
+ # other iterable of some kind
234
+ if not isinstance (data , (list , tuple )):
235
+ data = list (data )
236
+
237
+ data = np .asarray (data )
238
+
239
+ if np .issubdtype (data .dtype , np .datetime64 ):
240
+ data = dt64arr_to_periodarr (data , freq , tz )
241
+ return cls ._from_ordinals (data , name = name , freq = freq )
242
+
243
+ inferred_dtype = infer_dtype (data )
244
+
245
+ if inferred_dtype == 'floating' and len (data ) > 0 :
246
+ raise TypeError ("PeriodIndex can't take floats" )
247
+
248
+ else :
249
+ data = _ensure_object (data )
250
+ freq = freq or period .extract_freq (data )
251
+ data = period .extract_ordinals (data , freq )
252
+ return cls ._from_ordinals (data , name = name , freq = freq )
219
253
220
254
@classmethod
221
255
def _generate_range (cls , start , end , periods , freq , fields ):
@@ -236,68 +270,6 @@ def _generate_range(cls, start, end, periods, freq, fields):
236
270
237
271
return subarr , freq
238
272
239
- @classmethod
240
- def _from_arraylike (cls , data , freq , tz ):
241
- if freq is not None :
242
- freq = Period ._maybe_convert_freq (freq )
243
-
244
- if not isinstance (data , (np .ndarray , PeriodIndex ,
245
- DatetimeIndex , Int64Index )):
246
- if is_scalar (data ) or isinstance (data , Period ):
247
- raise ValueError ('PeriodIndex() must be called with a '
248
- 'collection of some kind, %s was passed'
249
- % repr (data ))
250
-
251
- # other iterable of some kind
252
- if not isinstance (data , (list , tuple )):
253
- data = list (data )
254
-
255
- try :
256
- data = _ensure_int64 (data )
257
- if freq is None :
258
- raise ValueError ('freq not specified' )
259
- data = np .array ([Period (x , freq = freq ) for x in data ],
260
- dtype = np .int64 )
261
- except (TypeError , ValueError ):
262
- data = _ensure_object (data )
263
-
264
- if freq is None :
265
- freq = period .extract_freq (data )
266
- data = period .extract_ordinals (data , freq )
267
- else :
268
- if isinstance (data , PeriodIndex ):
269
- if freq is None or freq == data .freq :
270
- freq = data .freq
271
- data = data ._values
272
- else :
273
- base1 , _ = _gfc (data .freq )
274
- base2 , _ = _gfc (freq )
275
- data = period .period_asfreq_arr (data ._values ,
276
- base1 , base2 , 1 )
277
- else :
278
- if is_object_dtype (data ):
279
- inferred = infer_dtype (data )
280
- if inferred == 'integer' :
281
- data = data .astype (np .int64 )
282
-
283
- if freq is None and is_object_dtype (data ):
284
- # must contain Period instance and thus extract ordinals
285
- freq = period .extract_freq (data )
286
- data = period .extract_ordinals (data , freq )
287
-
288
- if freq is None :
289
- msg = 'freq not specified and cannot be inferred'
290
- raise ValueError (msg )
291
-
292
- if data .dtype != np .int64 :
293
- if np .issubdtype (data .dtype , np .datetime64 ):
294
- data = dt64arr_to_periodarr (data , freq , tz )
295
- else :
296
- data = _ensure_object (data )
297
- data = period .extract_ordinals (data , freq )
298
-
299
- return data , freq
300
-
301
273
@classmethod
302
274
def _simple_new (cls , values , name = None , freq = None , ** kwargs ):
303
275
@@ -308,13 +280,18 @@ def _simple_new(cls, values, name=None, freq=None, **kwargs):
308
280
else :
309
281
return cls (values , name = name , freq = freq , ** kwargs )
310
282
283
+ return cls ._from_ordinals (values , name , freq , ** kwargs )
284
+
285
+ @classmethod
286
+ def _from_ordinals (cls , values , name = None , freq = None , ** kwargs ):
287
+
311
288
values = np .array (values , dtype = 'int64' , copy = False )
312
289
313
290
result = object .__new__ (cls )
314
291
result ._data = values
315
292
result .name = name
316
293
if freq is None :
317
- raise ValueError ('freq is not specified' )
294
+ raise ValueError ('freq is not specified and cannot be inferred ' )
318
295
result .freq = Period ._maybe_convert_freq (freq )
319
296
result ._reset_identity ()
320
297
return result
@@ -325,7 +302,6 @@ def _shallow_copy_with_infer(self, values=None, **kwargs):
325
302
326
303
def _shallow_copy (self , values = None , ** kwargs ):
327
304
if kwargs .get ('freq' ) is None :
328
- # freq must be provided
329
305
kwargs ['freq' ] = self .freq
330
306
if values is None :
331
307
values = self ._values
@@ -409,7 +385,7 @@ def __array_wrap__(self, result, context=None):
409
385
return result
410
386
# the result is object dtype array of Period
411
387
# cannot pass _simple_new as it is
412
- return PeriodIndex (result , freq = self .freq , name = self .name )
388
+ return self . _shallow_copy (result , freq = self .freq , name = self .name )
413
389
414
390
@property
415
391
def _box_func (self ):
@@ -704,7 +680,7 @@ def shift(self, n):
704
680
values = self ._values + n * self .freq .n
705
681
if self .hasnans :
706
682
values [self ._isnan ] = tslib .iNaT
707
- return PeriodIndex ( data = values , name = self . name , freq = self . freq )
683
+ return self . _shallow_copy ( values = values )
708
684
709
685
@cache_readonly
710
686
def dtype (self ):
@@ -940,7 +916,8 @@ def _wrap_union_result(self, other, result):
940
916
941
917
def _apply_meta (self , rawarr ):
942
918
if not isinstance (rawarr , PeriodIndex ):
943
- rawarr = PeriodIndex (rawarr , freq = self .freq )
919
+ rawarr = PeriodIndex ._from_ordinals (rawarr , freq = self .freq ,
920
+ name = self .name )
944
921
return rawarr
945
922
946
923
def _format_native_types (self , na_rep = u ('NaT' ), date_format = None ,
0 commit comments