@@ -41,11 +41,13 @@ def f(self):
41
41
42
42
43
43
def _get_ordinals (data , freq ):
44
- f = lambda x : Period (x , freq = freq ).ordinal
45
- if isinstance (data [0 ], Period ):
44
+ if len (data ) == 0 :
45
+ return np .array ([], dtype = 'int64' )
46
+ elif isinstance (data [0 ], Period ):
46
47
return period .extract_ordinals (data , freq )
47
- else :
48
- return lib .map_infer (data , f )
48
+ if com .is_float_dtype (data ):
49
+ raise ValueError ("PeriodIndex can't be constructed from floats" )
50
+ return lib .map_infer (data , lambda x : Period (x , freq = freq ).ordinal )
49
51
50
52
51
53
def dt64arr_to_periodarr (data , freq , tz ):
@@ -188,9 +190,43 @@ def __new__(cls, data=None, ordinal=None, freq=None, start=None, end=None,
188
190
else :
189
191
data , freq = cls ._generate_range (start , end , periods ,
190
192
freq , kwargs )
191
- else :
192
- ordinal , freq = cls ._from_arraylike (data , freq , tz )
193
- data = np .array (ordinal , dtype = np .int64 , copy = False )
193
+ return cls ._simple_new (data , name = name , freq = freq )
194
+
195
+ if isinstance (data , PeriodIndex ):
196
+ if freq is None or freq == data .freq :
197
+ freq = data .freq
198
+ data = data .values
199
+ else :
200
+ base1 , _ = _gfc (data .freq )
201
+ base2 , _ = _gfc (freq )
202
+ data = period .period_asfreq_arr (
203
+ data .values , base1 , base2 , 1 )
204
+ return cls ._simple_new (data , name = name , freq = freq )
205
+
206
+ if not isinstance (data , (np .ndarray , PeriodIndex ,
207
+ DatetimeIndex , Int64Index )):
208
+ if lib .isscalar (data ):
209
+ raise ValueError ('PeriodIndex() must be called with a '
210
+ 'collection of some kind, %r was passed'
211
+ % data )
212
+
213
+ # other iterable of some kind
214
+ if not isinstance (data , (list , tuple )):
215
+ data = list (data )
216
+
217
+ data = np .array (data , copy = False )
218
+
219
+ if freq is None and len (data ) > 0 :
220
+ freq = getattr (data [0 ], 'freq' , None )
221
+ if freq is None :
222
+ raise ValueError ('freq not specified and cannot be '
223
+ 'inferred from first element' )
224
+
225
+ if np .issubdtype (data .dtype , np .datetime64 ):
226
+ data = dt64arr_to_periodarr (data , freq , tz )
227
+ return cls ._simple_new (data , name = name , freq = freq )
228
+
229
+ data = _get_ordinals (data , freq )
194
230
195
231
return cls ._simple_new (data , name = name , freq = freq )
196
232
@@ -211,96 +247,23 @@ def _generate_range(cls, start, end, periods, freq, fields):
211
247
return subarr , freq
212
248
213
249
@classmethod
214
- def _from_arraylike (cls , data , freq , tz ):
215
- if not isinstance (data , (np .ndarray , PeriodIndex ,
216
- DatetimeIndex , Int64Index )):
217
- if lib .isscalar (data ) or isinstance (data , Period ):
218
- raise ValueError ('PeriodIndex() must be called with a '
219
- 'collection of some kind, %s was passed'
220
- % repr (data ))
221
-
222
- # other iterable of some kind
223
- if not isinstance (data , (list , tuple )):
224
- data = list (data )
225
-
226
- try :
227
- data = com ._ensure_int64 (data )
228
- if freq is None :
229
- raise ValueError ('freq not specified' )
230
- data = np .array ([Period (x , freq = freq ).ordinal for x in data ],
231
- dtype = np .int64 )
232
- except (TypeError , ValueError ):
233
- data = com ._ensure_object (data )
234
-
235
- if freq is None and len (data ) > 0 :
236
- freq = getattr (data [0 ], 'freq' , None )
237
-
238
- if freq is None :
239
- raise ValueError ('freq not specified and cannot be '
240
- 'inferred from first element' )
241
-
242
- data = _get_ordinals (data , freq )
243
- else :
244
- if isinstance (data , PeriodIndex ):
245
- if freq is None or freq == data .freq :
246
- freq = data .freq
247
- data = data .values
248
- else :
249
- base1 , _ = _gfc (data .freq )
250
- base2 , _ = _gfc (freq )
251
- data = period .period_asfreq_arr (data .values ,
252
- base1 , base2 , 1 )
253
- else :
254
- if freq is None and len (data ) > 0 :
255
- freq = getattr (data [0 ], 'freq' , None )
256
-
257
- if freq is None :
258
- raise ValueError ('freq not specified and cannot be '
259
- 'inferred from first element' )
260
-
261
- if data .dtype != np .int64 :
262
- if np .issubdtype (data .dtype , np .datetime64 ):
263
- data = dt64arr_to_periodarr (data , freq , tz )
264
- else :
265
- try :
266
- data = com ._ensure_int64 (data )
267
- except (TypeError , ValueError ):
268
- data = com ._ensure_object (data )
269
- data = _get_ordinals (data , freq )
270
-
271
- return data , freq
272
-
273
- @classmethod
274
- def _simple_new (cls , values , name = None , freq = None , ** kwargs ):
250
+ def _simple_new (cls , data , name = None , freq = None , ** kwargs ):
251
+ """ PeriodIndex from array-like of either ints or Periods """
275
252
276
- if not com .is_integer_dtype (values ):
277
- values = np .array (values , copy = False )
278
- if (len (values ) > 0 and com .is_float_dtype (values )):
279
- raise TypeError ("PeriodIndex can't take floats" )
280
- else :
281
- return PeriodIndex (values , name = name , freq = freq , ** kwargs )
253
+ if not com .is_integer_dtype (data ):
254
+ return PeriodIndex (data , name = name , freq = freq , ** kwargs )
282
255
283
- values = np .array (values , dtype = 'int64' , copy = False )
256
+ data = np .array (data , dtype = 'int64' , copy = False )
284
257
285
258
result = object .__new__ (cls )
286
- result ._data = values
259
+ result ._data = data
287
260
result .name = name
288
261
if freq is None :
289
262
raise ValueError ('freq is not specified' )
290
263
result .freq = Period ._maybe_convert_freq (freq )
291
264
result ._reset_identity ()
292
265
return result
293
266
294
- def _shallow_copy_with_infer (self , values = None , ** kwargs ):
295
- """ we always want to return a PeriodIndex """
296
- return self ._shallow_copy (values = values , ** kwargs )
297
-
298
- def _shallow_copy (self , values = None , ** kwargs ):
299
- if kwargs .get ('freq' ) is None :
300
- # freq must be provided
301
- kwargs ['freq' ] = self .freq
302
- return super (PeriodIndex , self )._shallow_copy (values = values , ** kwargs )
303
-
304
267
def _coerce_scalar_to_index (self , item ):
305
268
"""
306
269
we need to coerce a scalar to a compat for our index type
@@ -348,7 +311,7 @@ def __array_wrap__(self, result, context=None):
348
311
349
312
if com .is_bool_dtype (result ):
350
313
return result
351
- return PeriodIndex ( result , freq = self .freq , name = self . name )
314
+ return self ._shallow_copy ( result )
352
315
353
316
@property
354
317
def _box_func (self ):
@@ -646,7 +609,7 @@ def shift(self, n):
646
609
values = self .values + n * self .freq .n
647
610
if self .hasnans :
648
611
values [self ._isnan ] = tslib .iNaT
649
- return PeriodIndex ( data = values , name = self .name , freq = self . freq )
612
+ return self ._shallow_copy ( values )
650
613
651
614
@cache_readonly
652
615
def dtype_str (self ):
@@ -851,7 +814,7 @@ def _wrap_union_result(self, other, result):
851
814
852
815
def _apply_meta (self , rawarr ):
853
816
if not isinstance (rawarr , PeriodIndex ):
854
- rawarr = PeriodIndex ( rawarr , freq = self .freq )
817
+ rawarr = self ._shallow_copy ( rawarr )
855
818
return rawarr
856
819
857
820
def __getitem__ (self , key ):
@@ -869,9 +832,9 @@ def __getitem__(self, key):
869
832
# values = np.asarray(list(values), dtype=object)
870
833
# return values.reshape(result.shape)
871
834
872
- return PeriodIndex ( result , name = self .name , freq = self . freq )
835
+ return self ._shallow_copy ( result )
873
836
874
- return PeriodIndex ( result , name = self .name , freq = self . freq )
837
+ return self ._shallow_copy ( result )
875
838
876
839
def _format_native_types (self , na_rep = u ('NaT' ), date_format = None ,
877
840
** kwargs ):
@@ -921,7 +884,7 @@ def append(self, other):
921
884
to_concat = [x .asobject .values for x in to_concat ]
922
885
else :
923
886
cat_values = np .concatenate ([x .values for x in to_concat ])
924
- return PeriodIndex ( cat_values , freq = self .freq , name = name )
887
+ return self ._shallow_copy ( cat_values )
925
888
926
889
to_concat = [x .values if isinstance (x , Index ) else x
927
890
for x in to_concat ]
@@ -1143,3 +1106,4 @@ def period_range(start=None, end=None, periods=None, freq='D', name=None):
1143
1106
"""
1144
1107
return PeriodIndex (start = start , end = end , periods = periods ,
1145
1108
freq = freq , name = name )
1109
+
0 commit comments