Skip to content

Commit 368643f

Browse files
DEPR: Deprecate Series.view (#56054)
Co-authored-by: Joris Van den Bossche <[email protected]>
1 parent 6f080bd commit 368643f

File tree

16 files changed

+37
-48
lines changed

16 files changed

+37
-48
lines changed

doc/source/whatsnew/v2.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ Other Deprecations
362362
- Deprecated :func:`read_gbq` and :meth:`DataFrame.to_gbq`. Use ``pandas_gbq.read_gbq`` and ``pandas_gbq.to_gbq`` instead https://pandas-gbq.readthedocs.io/en/latest/api.html (:issue:`55525`)
363363
- Deprecated :meth:`.DataFrameGroupBy.fillna` and :meth:`.SeriesGroupBy.fillna`; use :meth:`.DataFrameGroupBy.ffill`, :meth:`.DataFrameGroupBy.bfill` for forward and backward filling or :meth:`.DataFrame.fillna` to fill with a single value (or the Series equivalents) (:issue:`55718`)
364364
- Deprecated :meth:`Index.format`, use ``index.astype(str)`` or ``index.map(formatter)`` instead (:issue:`55413`)
365+
- Deprecated :meth:`Series.view`, use ``astype`` instead to change the dtype (:issue:`20251`)
365366
- Deprecated ``core.internals`` members ``Block``, ``ExtensionBlock``, and ``DatetimeTZBlock``, use public APIs instead (:issue:`55139`)
366367
- Deprecated ``year``, ``month``, ``quarter``, ``day``, ``hour``, ``minute``, and ``second`` keywords in the :class:`PeriodIndex` constructor, use :meth:`PeriodIndex.from_fields` instead (:issue:`55960`)
367368
- Deprecated allowing non-integer ``periods`` argument in :func:`date_range`, :func:`timedelta_range`, :func:`period_range`, and :func:`interval_range` (:issue:`56036`)

pandas/core/series.py

+11-31
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,10 @@ def view(self, dtype: Dtype | None = None) -> Series:
877877
"""
878878
Create a new view of the Series.
879879
880+
.. deprecated:: 2.2.0
881+
``Series.view`` is deprecated and will be removed in a future version.
882+
Use :meth:`Series.astype` as an alternative to change the dtype.
883+
880884
This function will return a new Series with a view of the same
881885
underlying values in memory, optionally reinterpreted with a new data
882886
type. The new data type must preserve the same size in bytes as to not
@@ -907,38 +911,14 @@ def view(self, dtype: Dtype | None = None) -> Series:
907911
908912
Examples
909913
--------
910-
>>> s = pd.Series([-2, -1, 0, 1, 2], dtype='int8')
911-
>>> s
912-
0 -2
913-
1 -1
914-
2 0
915-
3 1
916-
4 2
917-
dtype: int8
918-
919-
The 8 bit signed integer representation of `-1` is `0b11111111`, but
920-
the same bytes represent 255 if read as an 8 bit unsigned integer:
921-
922-
>>> us = s.view('uint8')
923-
>>> us
924-
0 254
925-
1 255
926-
2 0
927-
3 1
928-
4 2
929-
dtype: uint8
930-
931-
The views share the same underlying values:
932-
933-
>>> us[0] = 128
934-
>>> s
935-
0 -128
936-
1 -1
937-
2 0
938-
3 1
939-
4 2
940-
dtype: int8
914+
Use ``astype`` to change the dtype instead.
941915
"""
916+
warnings.warn(
917+
"Series.view is deprecated and will be removed in a future version. "
918+
"Use ``astype`` as an alternative to change the dtype.",
919+
FutureWarning,
920+
stacklevel=2,
921+
)
942922
# self.array instead of self._values so we piggyback on NumpyExtensionArray
943923
# implementation
944924
res_values = self.array.view(dtype)

pandas/core/window/ewm.py

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
is_datetime64_ns_dtype,
1616
is_numeric_dtype,
1717
)
18+
from pandas.core.dtypes.generic import ABCSeries
1819
from pandas.core.dtypes.missing import isna
1920

2021
from pandas.core import common
@@ -118,6 +119,8 @@ def _calculate_deltas(
118119
np.ndarray
119120
Diff of the times divided by the half-life
120121
"""
122+
if isinstance(times, ABCSeries):
123+
times = times._values
121124
_times = np.asarray(times.view(np.int64), dtype=np.float64)
122125
# TODO: generalize to non-nano?
123126
_halflife = float(Timedelta(halflife).as_unit("ns")._value)

pandas/io/stata.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -429,9 +429,9 @@ def parse_dates_safe(
429429
d["year"] = date_index._data.year
430430
d["month"] = date_index._data.month
431431
if days:
432-
days_in_ns = dates.view(np.int64) - to_datetime(
432+
days_in_ns = dates._values.view(np.int64) - to_datetime(
433433
d["year"], format="%Y"
434-
).view(np.int64)
434+
)._values.view(np.int64)
435435
d["days"] = days_in_ns // NS_PER_DAY
436436

437437
elif infer_dtype(dates, skipna=False) == "datetime":

pandas/tests/copy_view/test_methods.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,8 @@ def test_series_view(using_copy_on_write, warn_copy_on_write):
19341934
ser = Series([1, 2, 3])
19351935
ser_orig = ser.copy()
19361936

1937-
ser2 = ser.view()
1937+
with tm.assert_produces_warning(FutureWarning, match="is deprecated"):
1938+
ser2 = ser.view()
19381939
assert np.shares_memory(get_array(ser), get_array(ser2))
19391940
if using_copy_on_write:
19401941
assert not ser2._mgr._has_no_reference(0)

pandas/tests/frame/indexing/test_where.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,8 @@ def test_where_datetimelike_noop(self, dtype):
771771
# GH#45135, analogue to GH#44181 for Period don't raise on no-op
772772
# For td64/dt64/dt64tz we already don't raise, but also are
773773
# checking that we don't unnecessarily upcast to object.
774-
ser = Series(np.arange(3) * 10**9, dtype=np.int64).view(dtype)
774+
with tm.assert_produces_warning(FutureWarning, match="is deprecated"):
775+
ser = Series(np.arange(3) * 10**9, dtype=np.int64).view(dtype)
775776
df = ser.to_frame()
776777
mask = np.array([False, False, False])
777778

pandas/tests/frame/test_constructors.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1101,8 +1101,8 @@ def test_constructor_maskedarray_nonfloat(self):
11011101
mat2[0, 0] = 1
11021102
mat2[1, 2] = 2
11031103
frame = DataFrame(mat2, columns=["A", "B", "C"], index=[1, 2])
1104-
assert 1 == frame["A"].view("i8")[1]
1105-
assert 2 == frame["C"].view("i8")[2]
1104+
assert 1 == frame["A"].astype("i8")[1]
1105+
assert 2 == frame["C"].astype("i8")[2]
11061106

11071107
# masked bool promoted to object
11081108
mat = ma.masked_all((2, 3), dtype=bool)

pandas/tests/generic/test_finalize.py

-5
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@
3131
# - Callable: pass the constructed value with attrs set to this.
3232

3333
_all_methods = [
34-
(
35-
pd.Series,
36-
(np.array([0], dtype="float64")),
37-
operator.methodcaller("view", "int64"),
38-
),
3934
(pd.Series, ([0],), operator.methodcaller("take", [])),
4035
(pd.Series, ([0],), operator.methodcaller("__getitem__", [True])),
4136
(pd.Series, ([0],), operator.methodcaller("repeat", 2)),

pandas/tests/groupby/test_cumulative.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def test_cummax_i8_at_implementation_bound():
216216
# the minimum value used to be treated as NPY_NAT+1 instead of NPY_NAT
217217
# for int64 dtype GH#46382
218218
ser = Series([pd.NaT._value + n for n in range(5)])
219-
df = DataFrame({"A": 1, "B": ser, "C": ser.view("M8[ns]")})
219+
df = DataFrame({"A": 1, "B": ser, "C": ser._values.view("M8[ns]")})
220220
gb = df.groupby("A")
221221

222222
res = gb.cummax()

pandas/tests/groupby/test_timegrouper.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ def test_groupby_groups_periods(self):
726726

727727
def test_groupby_first_datetime64(self):
728728
df = DataFrame([(1, 1351036800000000000), (2, 1351036800000000000)])
729-
df[1] = df[1].view("M8[ns]")
729+
df[1] = df[1].astype("M8[ns]")
730730

731731
assert issubclass(df[1].dtype.type, np.datetime64)
732732

pandas/tests/io/json/test_pandas.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def test_frame_non_unique_columns(self, orient, data):
168168
# in milliseconds; these are internally stored in nanosecond,
169169
# so divide to get where we need
170170
# TODO: a to_epoch method would also solve; see GH 14772
171-
expected.iloc[:, 0] = expected.iloc[:, 0].view(np.int64) // 1000000
171+
expected.iloc[:, 0] = expected.iloc[:, 0].astype(np.int64) // 1000000
172172
elif orient == "split":
173173
expected = df
174174
expected.columns = ["x", "x.1"]

pandas/tests/io/test_sql.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,7 @@ def test_api_timedelta(conn, request):
19081908
name="foo",
19091909
)
19101910
else:
1911-
expected = df["foo"].view("int64")
1911+
expected = df["foo"].astype("int64")
19121912
tm.assert_series_equal(result["foo"], expected)
19131913

19141914

pandas/tests/series/methods/test_view.py

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
)
1010
import pandas._testing as tm
1111

12+
pytestmark = pytest.mark.filterwarnings(
13+
"ignore:Series.view is deprecated and will be removed in a future version.:FutureWarning" # noqa: E501
14+
)
15+
1216

1317
class TestView:
1418
def test_view_i8_to_datetimelike(self):

pandas/tests/series/test_constructors.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ def test_constructor_dtype_datetime64_10(self):
969969
# GH3414 related
970970
expected = Series(pydates, dtype="datetime64[ms]")
971971

972-
result = Series(Series(dates).view(np.int64) / 1000000, dtype="M8[ms]")
972+
result = Series(Series(dates).astype(np.int64) / 1000000, dtype="M8[ms]")
973973
tm.assert_series_equal(result, expected)
974974

975975
result = Series(dates, dtype="datetime64[ms]")

pandas/tests/test_algos.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ def test_isin_datetimelike_values_numeric_comps(self, dtype, dtype1):
976976
# Anything but object and we get all-False shortcut
977977

978978
dta = date_range("2013-01-01", periods=3)._values
979-
arr = Series(dta.view("i8")).view(dtype1)._values
979+
arr = Series(dta.view("i8")).array.view(dtype1)
980980

981981
comps = arr.view("i8").astype(dtype)
982982

pandas/tests/test_nanops.py

+4
Original file line numberDiff line numberDiff line change
@@ -1114,12 +1114,16 @@ def test_nanmean(self, unit):
11141114
expected = dti[1]
11151115

11161116
for obj in [dti, DatetimeArray(dti), Series(dti)]:
1117+
if isinstance(obj, Series):
1118+
obj = obj._values
11171119
result = nanops.nanmean(obj)
11181120
assert result == expected
11191121

11201122
dti2 = dti.insert(1, pd.NaT)
11211123

11221124
for obj in [dti2, DatetimeArray(dti2), Series(dti2)]:
1125+
if isinstance(obj, Series):
1126+
obj = obj._values
11231127
result = nanops.nanmean(obj)
11241128
assert result == expected
11251129

0 commit comments

Comments
 (0)