Skip to content

Commit 73c8d23

Browse files
reidy-pharisbal
authored and
harisbal
committed
DEPR: Deprecate from_items (pandas-dev#18529)
1 parent 1c64d7d commit 73c8d23

File tree

8 files changed

+106
-63
lines changed

8 files changed

+106
-63
lines changed

doc/source/whatsnew/v0.23.0.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ Deprecations
329329
- :func:`read_excel` has deprecated the ``skip_footer`` parameter. Use ``skipfooter`` instead (:issue:`18836`)
330330
- The ``is_copy`` attribute is deprecated and will be removed in a future version (:issue:`18801`).
331331
- ``IntervalIndex.from_intervals`` is deprecated in favor of the :class:`IntervalIndex` constructor (:issue:`19263`)
332-
332+
- :func:``DataFrame.from_items`` is deprecated. Use :func:``DataFrame.from_dict()`` instead, or :func:``DataFrame.from_dict(OrderedDict())`` if you wish to preserve the key order (:issue:`17320`)
333333

334334
.. _whatsnew_0230.prior_deprecations:
335335

pandas/core/frame.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ def _constructor(self):
313313

314314
_constructor_sliced = Series
315315
_deprecations = NDFrame._deprecations | frozenset(
316-
['sortlevel', 'get_value', 'set_value', 'from_csv'])
316+
['sortlevel', 'get_value', 'set_value', 'from_csv', 'from_items'])
317317

318318
@property
319319
def _constructor_expanddim(self):
@@ -1246,6 +1246,12 @@ def to_records(self, index=True, convert_datetime64=True):
12461246
@classmethod
12471247
def from_items(cls, items, columns=None, orient='columns'):
12481248
"""
1249+
.. deprecated:: 0.23.0
1250+
from_items is deprecated and will be removed in a
1251+
future version. Use :meth:`DataFrame.from_dict(dict())`
1252+
instead. :meth:`DataFrame.from_dict(OrderedDict(...))` may be used
1253+
to preserve the key order.
1254+
12491255
Convert (key, value) pairs to DataFrame. The keys will be the axis
12501256
index (usually the columns, but depends on the specified
12511257
orientation). The values should be arrays or Series.
@@ -1266,6 +1272,13 @@ def from_items(cls, items, columns=None, orient='columns'):
12661272
-------
12671273
frame : DataFrame
12681274
"""
1275+
1276+
warnings.warn("from_items is deprecated. Please use "
1277+
"DataFrame.from_dict(dict()) instead. "
1278+
"DataFrame.from_dict(OrderedDict()) may be used to "
1279+
"preserve the key order.",
1280+
FutureWarning, stacklevel=2)
1281+
12691282
keys, values = lzip(*items)
12701283

12711284
if orient == 'columns':

pandas/io/stata.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import datetime
1414
import struct
1515
import sys
16+
from collections import OrderedDict
1617

1718
import numpy as np
1819
from dateutil.relativedelta import relativedelta
@@ -1571,7 +1572,7 @@ def read(self, nrows=None, convert_dates=None,
15711572
else:
15721573
data_formatted.append((col, data[col]))
15731574
if requires_type_conversion:
1574-
data = DataFrame.from_items(data_formatted)
1575+
data = DataFrame.from_dict(OrderedDict(data_formatted))
15751576
del data_formatted
15761577

15771578
self._do_convert_missing(data, convert_missing)
@@ -1609,7 +1610,7 @@ def read(self, nrows=None, convert_dates=None,
16091610
convert = True
16101611
retyped_data.append((col, data[col].astype(dtype)))
16111612
if convert:
1612-
data = DataFrame.from_items(retyped_data)
1613+
data = DataFrame.from_dict(OrderedDict(retyped_data))
16131614

16141615
if index_col is not None:
16151616
data = data.set_index(data.pop(index_col))
@@ -1722,7 +1723,7 @@ def _do_convert_categoricals(self, data, value_label_dict, lbllist,
17221723
cat_converted_data.append((col, cat_data))
17231724
else:
17241725
cat_converted_data.append((col, data[col]))
1725-
data = DataFrame.from_items(cat_converted_data)
1726+
data = DataFrame.from_dict(OrderedDict(cat_converted_data))
17261727
return data
17271728

17281729
def data_label(self):
@@ -1997,7 +1998,7 @@ def _prepare_categoricals(self, data):
19971998
data_formatted.append((col, values))
19981999
else:
19992000
data_formatted.append((col, data[col]))
2000-
return DataFrame.from_items(data_formatted)
2001+
return DataFrame.from_dict(OrderedDict(data_formatted))
20012002

20022003
def _replace_nans(self, data):
20032004
# return data

pandas/tests/frame/test_constructors.py

+48-21
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ def __len__(self, n):
871871
# GH 4297
872872
# support Array
873873
import array
874-
result = DataFrame.from_items([('A', array.array('i', range(10)))])
874+
result = DataFrame({'A': array.array('i', range(10))})
875875
expected = DataFrame({'A': list(range(10))})
876876
tm.assert_frame_equal(result, expected, check_dtype=False)
877877

@@ -1175,44 +1175,55 @@ def test_constructor_manager_resize(self):
11751175

11761176
def test_constructor_from_items(self):
11771177
items = [(c, self.frame[c]) for c in self.frame.columns]
1178-
recons = DataFrame.from_items(items)
1178+
with tm.assert_produces_warning(FutureWarning,
1179+
check_stacklevel=False):
1180+
recons = DataFrame.from_items(items)
11791181
tm.assert_frame_equal(recons, self.frame)
11801182

11811183
# pass some columns
1182-
recons = DataFrame.from_items(items, columns=['C', 'B', 'A'])
1184+
with tm.assert_produces_warning(FutureWarning,
1185+
check_stacklevel=False):
1186+
recons = DataFrame.from_items(items, columns=['C', 'B', 'A'])
11831187
tm.assert_frame_equal(recons, self.frame.loc[:, ['C', 'B', 'A']])
11841188

11851189
# orient='index'
11861190

11871191
row_items = [(idx, self.mixed_frame.xs(idx))
11881192
for idx in self.mixed_frame.index]
1189-
1190-
recons = DataFrame.from_items(row_items,
1191-
columns=self.mixed_frame.columns,
1192-
orient='index')
1193+
with tm.assert_produces_warning(FutureWarning,
1194+
check_stacklevel=False):
1195+
recons = DataFrame.from_items(row_items,
1196+
columns=self.mixed_frame.columns,
1197+
orient='index')
11931198
tm.assert_frame_equal(recons, self.mixed_frame)
11941199
assert recons['A'].dtype == np.float64
11951200

11961201
with tm.assert_raises_regex(TypeError,
11971202
"Must pass columns with "
11981203
"orient='index'"):
1199-
DataFrame.from_items(row_items, orient='index')
1204+
with tm.assert_produces_warning(FutureWarning,
1205+
check_stacklevel=False):
1206+
DataFrame.from_items(row_items, orient='index')
12001207

12011208
# orient='index', but thar be tuples
12021209
arr = construct_1d_object_array_from_listlike(
12031210
[('bar', 'baz')] * len(self.mixed_frame))
12041211
self.mixed_frame['foo'] = arr
12051212
row_items = [(idx, list(self.mixed_frame.xs(idx)))
12061213
for idx in self.mixed_frame.index]
1207-
recons = DataFrame.from_items(row_items,
1208-
columns=self.mixed_frame.columns,
1209-
orient='index')
1214+
with tm.assert_produces_warning(FutureWarning,
1215+
check_stacklevel=False):
1216+
recons = DataFrame.from_items(row_items,
1217+
columns=self.mixed_frame.columns,
1218+
orient='index')
12101219
tm.assert_frame_equal(recons, self.mixed_frame)
12111220
assert isinstance(recons['foo'][0], tuple)
12121221

1213-
rs = DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6])],
1214-
orient='index',
1215-
columns=['one', 'two', 'three'])
1222+
with tm.assert_produces_warning(FutureWarning,
1223+
check_stacklevel=False):
1224+
rs = DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6])],
1225+
orient='index',
1226+
columns=['one', 'two', 'three'])
12161227
xp = DataFrame([[1, 2, 3], [4, 5, 6]], index=['A', 'B'],
12171228
columns=['one', 'two', 'three'])
12181229
tm.assert_frame_equal(rs, xp)
@@ -1222,12 +1233,28 @@ def test_constructor_from_items_scalars(self):
12221233
with tm.assert_raises_regex(ValueError,
12231234
r'The value in each \(key, value\) '
12241235
'pair must be an array, Series, or dict'):
1225-
DataFrame.from_items([('A', 1), ('B', 4)])
1236+
with tm.assert_produces_warning(FutureWarning,
1237+
check_stacklevel=False):
1238+
DataFrame.from_items([('A', 1), ('B', 4)])
12261239

12271240
with tm.assert_raises_regex(ValueError,
12281241
r'The value in each \(key, value\) '
12291242
'pair must be an array, Series, or dict'):
1230-
DataFrame.from_items([('A', 1), ('B', 2)], columns=['col1'],
1243+
with tm.assert_produces_warning(FutureWarning,
1244+
check_stacklevel=False):
1245+
DataFrame.from_items([('A', 1), ('B', 2)], columns=['col1'],
1246+
orient='index')
1247+
1248+
def test_from_items_deprecation(self):
1249+
# GH 17320
1250+
with tm.assert_produces_warning(FutureWarning,
1251+
check_stacklevel=False):
1252+
DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6])])
1253+
1254+
with tm.assert_produces_warning(FutureWarning,
1255+
check_stacklevel=False):
1256+
DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6])],
1257+
columns=['col1', 'col2', 'col3'],
12311258
orient='index')
12321259

12331260
def test_constructor_mix_series_nonseries(self):
@@ -1256,13 +1283,13 @@ def test_constructor_column_duplicates(self):
12561283

12571284
tm.assert_frame_equal(df, edf)
12581285

1259-
idf = DataFrame.from_items(
1260-
[('a', [8]), ('a', [5])], columns=['a', 'a'])
1286+
idf = DataFrame.from_records([(8, 5)],
1287+
columns=['a', 'a'])
1288+
12611289
tm.assert_frame_equal(idf, edf)
12621290

1263-
pytest.raises(ValueError, DataFrame.from_items,
1264-
[('a', [8]), ('a', [5]), ('b', [6])],
1265-
columns=['b', 'a', 'a'])
1291+
pytest.raises(ValueError, DataFrame.from_dict,
1292+
OrderedDict([('b', 8), ('a', 5), ('a', 6)]))
12661293

12671294
def test_constructor_empty_with_string_dtype(self):
12681295
# GH 9428

pandas/tests/frame/test_nonunique_indexes.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,10 @@ def check(result, expected=None):
214214
for index in [df.index, pd.Index(list('edcba'))]:
215215
this_df = df.copy()
216216
expected_ser = pd.Series(index.values, index=this_df.index)
217-
expected_df = DataFrame.from_items([('A', expected_ser),
218-
('B', this_df['B']),
219-
('A', expected_ser)])
217+
expected_df = DataFrame({'A': expected_ser,
218+
'B': this_df['B'],
219+
'A': expected_ser},
220+
columns=['A', 'B', 'A'])
220221
this_df['A'] = index
221222
check(this_df, expected_df)
222223

pandas/tests/io/parser/common.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import re
99
import sys
1010
from datetime import datetime
11+
from collections import OrderedDict
1112

1213
import pytest
1314
import numpy as np
@@ -924,8 +925,9 @@ def test_float_parser(self):
924925

925926
def test_scientific_no_exponent(self):
926927
# see gh-12215
927-
df = DataFrame.from_items([('w', ['2e']), ('x', ['3E']),
928-
('y', ['42e']), ('z', ['632E'])])
928+
df = DataFrame.from_dict(OrderedDict([('w', ['2e']), ('x', ['3E']),
929+
('y', ['42e']),
930+
('z', ['632E'])]))
929931
data = df.to_csv(index=False)
930932
for prec in self.float_precision_choices:
931933
df_roundtrip = self.read_csv(

pandas/tests/io/test_excel.py

+28-30
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from distutils.version import LooseVersion
77
from functools import partial
88
from warnings import catch_warnings
9+
from collections import OrderedDict
910

1011
import numpy as np
1112
import pytest
@@ -315,7 +316,7 @@ def test_excel_table(self):
315316

316317
def test_reader_special_dtypes(self):
317318

318-
expected = DataFrame.from_items([
319+
expected = DataFrame.from_dict(OrderedDict([
319320
("IntCol", [1, 2, -3, 4, 0]),
320321
("FloatCol", [1.25, 2.25, 1.83, 1.92, 0.0000000005]),
321322
("BoolCol", [True, False, True, True, False]),
@@ -325,8 +326,7 @@ def test_reader_special_dtypes(self):
325326
("DateCol", [datetime(2013, 10, 30), datetime(2013, 10, 31),
326327
datetime(1905, 1, 1), datetime(2013, 12, 14),
327328
datetime(2015, 3, 14)])
328-
])
329-
329+
]))
330330
basename = 'test_types'
331331

332332
# should read in correctly and infer types
@@ -363,12 +363,12 @@ def test_reader_converters(self):
363363

364364
basename = 'test_converters'
365365

366-
expected = DataFrame.from_items([
366+
expected = DataFrame.from_dict(OrderedDict([
367367
("IntCol", [1, 2, -3, -1000, 0]),
368368
("FloatCol", [12.5, np.nan, 18.3, 19.2, 0.000000005]),
369369
("BoolCol", ['Found', 'Found', 'Found', 'Not found', 'Found']),
370370
("StrCol", ['1', np.nan, '3', '4', '5']),
371-
])
371+
]))
372372

373373
converters = {'IntCol': lambda x: int(x) if x != '' else -1000,
374374
'FloatCol': lambda x: 10 * x if x else np.nan,
@@ -718,32 +718,30 @@ def test_reader_seconds(self):
718718

719719
if LooseVersion(xlrd.__VERSION__) >= LooseVersion("0.9.3"):
720720
# Xlrd >= 0.9.3 can handle Excel milliseconds.
721-
expected = DataFrame.from_items([("Time",
722-
[time(1, 2, 3),
723-
time(2, 45, 56, 100000),
724-
time(4, 29, 49, 200000),
725-
time(6, 13, 42, 300000),
726-
time(7, 57, 35, 400000),
727-
time(9, 41, 28, 500000),
728-
time(11, 25, 21, 600000),
729-
time(13, 9, 14, 700000),
730-
time(14, 53, 7, 800000),
731-
time(16, 37, 0, 900000),
732-
time(18, 20, 54)])])
721+
expected = DataFrame.from_dict({"Time": [time(1, 2, 3),
722+
time(2, 45, 56, 100000),
723+
time(4, 29, 49, 200000),
724+
time(6, 13, 42, 300000),
725+
time(7, 57, 35, 400000),
726+
time(9, 41, 28, 500000),
727+
time(11, 25, 21, 600000),
728+
time(13, 9, 14, 700000),
729+
time(14, 53, 7, 800000),
730+
time(16, 37, 0, 900000),
731+
time(18, 20, 54)]})
733732
else:
734733
# Xlrd < 0.9.3 rounds Excel milliseconds.
735-
expected = DataFrame.from_items([("Time",
736-
[time(1, 2, 3),
737-
time(2, 45, 56),
738-
time(4, 29, 49),
739-
time(6, 13, 42),
740-
time(7, 57, 35),
741-
time(9, 41, 29),
742-
time(11, 25, 22),
743-
time(13, 9, 15),
744-
time(14, 53, 8),
745-
time(16, 37, 1),
746-
time(18, 20, 54)])])
734+
expected = DataFrame.from_dict({"Time": [time(1, 2, 3),
735+
time(2, 45, 56),
736+
time(4, 29, 49),
737+
time(6, 13, 42),
738+
time(7, 57, 35),
739+
time(9, 41, 29),
740+
time(11, 25, 22),
741+
time(13, 9, 15),
742+
time(14, 53, 8),
743+
time(16, 37, 1),
744+
time(18, 20, 54)]})
747745

748746
actual = self.get_exceldf('times_1900', 'Sheet1')
749747
tm.assert_frame_equal(actual, expected)
@@ -1988,7 +1986,7 @@ def test_datetimes(self):
19881986
datetime(2013, 1, 13, 18, 20, 52)]
19891987

19901988
with ensure_clean(self.ext) as path:
1991-
write_frame = DataFrame.from_items([('A', datetimes)])
1989+
write_frame = DataFrame({'A': datetimes})
19921990
write_frame.to_excel(path, 'Sheet1')
19931991
read_frame = read_excel(path, 'Sheet1', header=0)
19941992

pandas/tests/io/test_stata.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import warnings
99
from datetime import datetime
1010
from distutils.version import LooseVersion
11+
from collections import OrderedDict
1112

1213
import numpy as np
1314
import pandas as pd
@@ -945,7 +946,7 @@ def test_categorical_order(self, file):
945946
cols.append((col, pd.Categorical.from_codes(codes, labels)))
946947
else:
947948
cols.append((col, pd.Series(labels, dtype=np.float32)))
948-
expected = DataFrame.from_items(cols)
949+
expected = DataFrame.from_dict(OrderedDict(cols))
949950

950951
# Read with and with out categoricals, ensure order is identical
951952
file = getattr(self, file)

0 commit comments

Comments
 (0)