|
93 | 93 | )
|
94 | 94 |
|
95 | 95 | from pandas.core.dtypes.cast import (
|
| 96 | + can_hold_element, |
96 | 97 | construct_1d_arraylike_from_scalar,
|
97 | 98 | construct_2d_arraylike_from_scalar,
|
98 | 99 | find_common_type,
|
@@ -5366,6 +5367,48 @@ def shift(
|
5366 | 5367 |
|
5367 | 5368 | result.columns = self.columns.copy()
|
5368 | 5369 | return result
|
| 5370 | + elif ( |
| 5371 | + axis == 1 |
| 5372 | + and periods != 0 |
| 5373 | + and fill_value is not lib.no_default |
| 5374 | + and ncols > 0 |
| 5375 | + ): |
| 5376 | + arrays = self._mgr.arrays |
| 5377 | + if len(arrays) > 1 or ( |
| 5378 | + # If we only have one block and we know that we can't |
| 5379 | + # keep the same dtype (i.e. the _can_hold_element check) |
| 5380 | + # then we can go through the reindex_indexer path |
| 5381 | + # (and avoid casting logic in the Block method). |
| 5382 | + # The exception to this (until 2.0) is datetimelike |
| 5383 | + # dtypes with integers, which cast. |
| 5384 | + not can_hold_element(arrays[0], fill_value) |
| 5385 | + # TODO(2.0): remove special case for integer-with-datetimelike |
| 5386 | + # once deprecation is enforced |
| 5387 | + and not ( |
| 5388 | + lib.is_integer(fill_value) and needs_i8_conversion(arrays[0].dtype) |
| 5389 | + ) |
| 5390 | + ): |
| 5391 | + # GH#35488 we need to watch out for multi-block cases |
| 5392 | + # We only get here with fill_value not-lib.no_default |
| 5393 | + nper = abs(periods) |
| 5394 | + nper = min(nper, ncols) |
| 5395 | + if periods > 0: |
| 5396 | + indexer = np.array( |
| 5397 | + [-1] * nper + list(range(ncols - periods)), dtype=np.intp |
| 5398 | + ) |
| 5399 | + else: |
| 5400 | + indexer = np.array( |
| 5401 | + list(range(nper, ncols)) + [-1] * nper, dtype=np.intp |
| 5402 | + ) |
| 5403 | + mgr = self._mgr.reindex_indexer( |
| 5404 | + self.columns, |
| 5405 | + indexer, |
| 5406 | + axis=0, |
| 5407 | + fill_value=fill_value, |
| 5408 | + allow_dups=True, |
| 5409 | + ) |
| 5410 | + res_df = self._constructor(mgr) |
| 5411 | + return res_df.__finalize__(self, method="shift") |
5369 | 5412 |
|
5370 | 5413 | return super().shift(
|
5371 | 5414 | periods=periods, freq=freq, axis=axis, fill_value=fill_value
|
|
0 commit comments