@@ -5279,45 +5279,28 @@ def shift(
5279
5279
axis = self ._get_axis_number (axis )
5280
5280
5281
5281
ncols = len (self .columns )
5282
+ if axis == 1 and periods != 0 and fill_value is lib .no_default and ncols > 0 :
5283
+ # We will infer fill_value to match the closest column
5282
5284
5283
- if (
5284
- axis == 1
5285
- and periods != 0
5286
- and ncols > 0
5287
- and (fill_value is lib .no_default or len (self ._mgr .arrays ) > 1 )
5288
- ):
5289
- # Exclude single-array-with-fill_value case so we issue a FutureWarning
5290
- # if an integer is passed with datetimelike dtype GH#31971
5291
- from pandas import concat
5285
+ # Use a column that we know is valid for our column's dtype GH#38434
5286
+ label = self .columns [0 ]
5292
5287
5293
- # tail: the data that is still in our shifted DataFrame
5294
5288
if periods > 0 :
5295
- tail = self .iloc [:, :- periods ]
5296
- else :
5297
- tail = self .iloc [:, - periods :]
5298
- # pin a simple Index to avoid costly casting
5299
- tail .columns = range (len (tail .columns ))
5300
-
5301
- if fill_value is not lib .no_default :
5302
- # GH#35488
5303
- # TODO(EA2D): with 2D EAs we could construct other directly
5304
- ser = Series (fill_value , index = self .index )
5289
+ result = self .iloc [:, :- periods ]
5290
+ for col in range (min (ncols , abs (periods ))):
5291
+ # TODO(EA2D): doing this in a loop unnecessary with 2D EAs
5292
+ # Define filler inside loop so we get a copy
5293
+ filler = self .iloc [:, 0 ].shift (len (self ))
5294
+ result .insert (0 , label , filler , allow_duplicates = True )
5305
5295
else :
5306
- # We infer fill_value to match the closest column
5307
- if periods > 0 :
5308
- ser = self .iloc [:, 0 ].shift (len (self ))
5309
- else :
5310
- ser = self .iloc [:, - 1 ].shift (len (self ))
5311
-
5312
- width = min (abs (periods ), ncols )
5313
- other = concat ([ser ] * width , axis = 1 )
5314
-
5315
- if periods > 0 :
5316
- result = concat ([other , tail ], axis = 1 )
5317
- else :
5318
- result = concat ([tail , other ], axis = 1 )
5296
+ result = self .iloc [:, - periods :]
5297
+ for col in range (min (ncols , abs (periods ))):
5298
+ # Define filler inside loop so we get a copy
5299
+ filler = self .iloc [:, - 1 ].shift (len (self ))
5300
+ result .insert (
5301
+ len (result .columns ), label , filler , allow_duplicates = True
5302
+ )
5319
5303
5320
- result = cast (DataFrame , result )
5321
5304
result .columns = self .columns .copy ()
5322
5305
return result
5323
5306
0 commit comments