@@ -5279,45 +5279,28 @@ def shift(
52795279 axis = self ._get_axis_number (axis )
52805280
52815281 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
52825284
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 ]
52925287
5293- # tail: the data that is still in our shifted DataFrame
52945288 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 )
53055295 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+ )
53195303
5320- result = cast (DataFrame , result )
53215304 result .columns = self .columns .copy ()
53225305 return result
53235306
0 commit comments