Skip to content

Commit 3d47fb9

Browse files
authored
DEP: Deprecate passing a DataFrame to from_records (#51697)
1 parent b39efd9 commit 3d47fb9

File tree

4 files changed

+37
-23
lines changed

4 files changed

+37
-23
lines changed

doc/source/whatsnew/v2.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ Other API changes
9393
Deprecations
9494
~~~~~~~~~~~~
9595
- Deprecating pinning ``group.name`` to each group in :meth:`SeriesGroupBy.aggregate` aggregations; if your operation requires utilizing the groupby keys, iterate over the groupby object instead (:issue:`41090`)
96+
- Deprecated passing a :class:`DataFrame` to :meth:`DataFrame.from_records`, use :meth:`DataFrame.set_index` or :meth:`DataFrame.drop` instead (:issue:`51353`)
9697
- Deprecated accepting slices in :meth:`DataFrame.take`, call ``obj[slicer]`` or pass a sequence of integers instead (:issue:`51539`)
9798
-
9899

pandas/core/frame.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -2109,6 +2109,9 @@ def from_records(
21092109
----------
21102110
data : structured ndarray, sequence of tuples or dicts, or DataFrame
21112111
Structured input data.
2112+
2113+
.. deprecated:: 2.1.0
2114+
Passing a DataFrame is deprecated.
21122115
index : str, list of fields, array-like
21132116
Field of array to use as the index, alternately a specific set of
21142117
input labels to use.
@@ -2171,6 +2174,23 @@ def from_records(
21712174
2 1 c
21722175
3 0 d
21732176
"""
2177+
if isinstance(data, DataFrame):
2178+
warnings.warn(
2179+
"Passing a DataFrame to DataFrame.from_records is deprecated. Use "
2180+
"set_index and/or drop to modify the DataFrame instead.",
2181+
FutureWarning,
2182+
stacklevel=find_stack_level(),
2183+
)
2184+
if columns is not None:
2185+
if is_scalar(columns):
2186+
columns = [columns]
2187+
data = data[columns]
2188+
if index is not None:
2189+
data = data.set_index(index)
2190+
if exclude is not None:
2191+
data = data.drop(columns=exclude)
2192+
return data
2193+
21742194
result_index = None
21752195

21762196
# Make a copy of the input columns so we can modify it
@@ -2238,7 +2258,7 @@ def maybe_reorder(
22382258
arrays, arr_columns, columns, index
22392259
)
22402260

2241-
elif isinstance(data, (np.ndarray, DataFrame)):
2261+
elif isinstance(data, np.ndarray):
22422262
arrays, columns = to_arrays(data, columns)
22432263
arr_columns = columns
22442264
else:

pandas/core/internals/construction.py

-13
Original file line numberDiff line numberDiff line change
@@ -769,19 +769,6 @@ def to_arrays(
769769
-----
770770
Ensures that len(result_arrays) == len(result_index).
771771
"""
772-
if isinstance(data, ABCDataFrame):
773-
# see test_from_records_with_index_data, test_from_records_bad_index_column
774-
if columns is not None:
775-
arrays = [
776-
data._ixs(i, axis=1)._values
777-
for i, col in enumerate(data.columns)
778-
if col in columns
779-
]
780-
else:
781-
columns = data.columns
782-
arrays = [data._ixs(i, axis=1)._values for i in range(len(columns))]
783-
784-
return arrays, columns
785772

786773
if not len(data):
787774
if isinstance(data, np.ndarray):

pandas/tests/frame/constructors/test_from_records.py

+15-9
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ def test_from_records_dt64tz_frame(self):
2525
# GH#51162 don't lose tz when calling from_records with DataFrame input
2626
dti = date_range("2016-01-01", periods=10, tz="US/Pacific")
2727
df = DataFrame({i: dti for i in range(4)})
28-
res = DataFrame.from_records(df)
28+
with tm.assert_produces_warning(FutureWarning):
29+
res = DataFrame.from_records(df)
2930
tm.assert_frame_equal(res, df)
3031

3132
def test_from_records_with_datetimes(self):
@@ -177,29 +178,34 @@ def test_from_records_with_index_data(self):
177178
df = DataFrame(np.random.randn(10, 3), columns=["A", "B", "C"])
178179

179180
data = np.random.randn(10)
180-
df1 = DataFrame.from_records(df, index=data)
181+
with tm.assert_produces_warning(FutureWarning):
182+
df1 = DataFrame.from_records(df, index=data)
181183
tm.assert_index_equal(df1.index, Index(data))
182184

183185
def test_from_records_bad_index_column(self):
184186
df = DataFrame(np.random.randn(10, 3), columns=["A", "B", "C"])
185187

186188
# should pass
187-
df1 = DataFrame.from_records(df, index=["C"])
189+
with tm.assert_produces_warning(FutureWarning):
190+
df1 = DataFrame.from_records(df, index=["C"])
188191
tm.assert_index_equal(df1.index, Index(df.C))
189192

190-
df1 = DataFrame.from_records(df, index="C")
193+
with tm.assert_produces_warning(FutureWarning):
194+
df1 = DataFrame.from_records(df, index="C")
191195
tm.assert_index_equal(df1.index, Index(df.C))
192196

193197
# should fail
194198
msg = "|".join(
195199
[
196-
r"Length of values \(10\) does not match length of index \(1\)",
200+
r"'None of \[2\] are in the columns'",
197201
]
198202
)
199-
with pytest.raises(ValueError, match=msg):
200-
DataFrame.from_records(df, index=[2])
201-
with pytest.raises(KeyError, match=r"^2$"):
202-
DataFrame.from_records(df, index=2)
203+
with pytest.raises(KeyError, match=msg):
204+
with tm.assert_produces_warning(FutureWarning):
205+
DataFrame.from_records(df, index=[2])
206+
with pytest.raises(KeyError, match=msg):
207+
with tm.assert_produces_warning(FutureWarning):
208+
DataFrame.from_records(df, index=2)
203209

204210
def test_from_records_non_tuple(self):
205211
class Record:

0 commit comments

Comments
 (0)