@@ -5285,45 +5285,28 @@ def shift(
52855285 axis = self ._get_axis_number (axis )
52865286
52875287 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
52885290
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 ]
52985293
5299- # tail: the data that is still in our shifted DataFrame
53005294 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 )
53115301 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+ )
53255309
5326- result = cast (DataFrame , result )
53275310 result .columns = self .columns .copy ()
53285311 return result
53295312
0 commit comments