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