|
42 | 42 | infer_dtype_from, |
43 | 43 | maybe_downcast_numeric, |
44 | 44 | maybe_downcast_to_dtype, |
45 | | - maybe_upcast, |
46 | 45 | soft_convert_objects, |
47 | 46 | ) |
48 | 47 | from pandas.core.dtypes.common import ( |
@@ -1149,11 +1148,25 @@ def shift(self, periods: int, axis: int = 0, fill_value: Any = None) -> list[Blo |
1149 | 1148 | # convert integer to float if necessary. need to do a lot more than |
1150 | 1149 | # that, handle boolean etc also |
1151 | 1150 |
|
1152 | | - values = cast(np.ndarray, self.values) |
| 1151 | + # Note: periods is never 0 here, as that is handled at the top of |
| 1152 | + # NDFrame.shift. If that ever changes, we can do a check for periods=0 |
| 1153 | + # and possibly avoid coercing. |
| 1154 | + |
| 1155 | + if not lib.is_scalar(fill_value) and self.dtype != _dtype_obj: |
| 1156 | + # with object dtype there is nothing to promote, and the user can |
| 1157 | + # pass pretty much any weird fill_value they like |
| 1158 | + # see test_shift_object_non_scalar_fill |
| 1159 | + raise ValueError("fill_value must be a scalar") |
1153 | 1160 |
|
1154 | | - new_values, fill_value = maybe_upcast(values, fill_value) |
| 1161 | + if is_valid_na_for_dtype(fill_value, self.dtype) and self.dtype != _dtype_obj: |
| 1162 | + fill_value = self.fill_value |
1155 | 1163 |
|
1156 | | - new_values = shift(new_values, periods, axis, fill_value) |
| 1164 | + if not self._can_hold_element(fill_value): |
| 1165 | + nb = self.coerce_to_target_dtype(fill_value) |
| 1166 | + return nb.shift(periods, axis=axis, fill_value=fill_value) |
| 1167 | + |
| 1168 | + values = cast(np.ndarray, self.values) |
| 1169 | + new_values = shift(values, periods, axis, fill_value) |
1157 | 1170 |
|
1158 | 1171 | return [self.make_block(new_values)] |
1159 | 1172 |
|
|
0 commit comments