Skip to content

Commit f6fe089

Browse files
reidy-pjreback
authored andcommitted
EHN: Improve from_items error message (#17312) (#17881)
1 parent 29206ee commit f6fe089

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

doc/source/whatsnew/v0.22.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Other API Changes
8080
- :class:`IntervalIndex` constructor will raise if the ``closed`` parameter conflicts with how the input data is inferred to be closed (:issue:`18421`)
8181
- Inserting missing values into indexes will work for all types of indexes and automatically insert the correct type of missing value (``NaN``, ``NaT``, etc.) regardless of the type passed in (:issue:`18295`)
8282
- Restricted ``DateOffset`` keyword arguments. Previously, ``DateOffset`` subclasses allowed arbitrary keyword arguments which could lead to unexpected behavior. Now, only valid arguments will be accepted. (:issue:`17176`, :issue:`18226`).
83+
- :func:`DataFrame.from_items` provides a more informative error message when passed scalar values (:issue:`17312`)
8384

8485
.. _whatsnew_0220.deprecations:
8586

pandas/core/frame.py

+23-4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
_ensure_int64,
5555
_ensure_platform_int,
5656
is_list_like,
57+
is_nested_list_like,
5758
is_iterator,
5859
is_sequence,
5960
is_named_tuple)
@@ -1271,16 +1272,34 @@ def from_items(cls, items, columns=None, orient='columns'):
12711272
columns = _ensure_index(keys)
12721273
arrays = values
12731274

1274-
return cls._from_arrays(arrays, columns, None)
1275+
# GH 17312
1276+
# Provide more informative error msg when scalar values passed
1277+
try:
1278+
return cls._from_arrays(arrays, columns, None)
1279+
1280+
except ValueError:
1281+
if not is_nested_list_like(values):
1282+
raise ValueError('The value in each (key, value) pair '
1283+
'must be an array, Series, or dict')
1284+
12751285
elif orient == 'index':
12761286
if columns is None:
12771287
raise TypeError("Must pass columns with orient='index'")
12781288

12791289
keys = _ensure_index(keys)
12801290

1281-
arr = np.array(values, dtype=object).T
1282-
data = [lib.maybe_convert_objects(v) for v in arr]
1283-
return cls._from_arrays(data, columns, keys)
1291+
# GH 17312
1292+
# Provide more informative error msg when scalar values passed
1293+
try:
1294+
arr = np.array(values, dtype=object).T
1295+
data = [lib.maybe_convert_objects(v) for v in arr]
1296+
return cls._from_arrays(data, columns, keys)
1297+
1298+
except TypeError:
1299+
if not is_nested_list_like(values):
1300+
raise ValueError('The value in each (key, value) pair '
1301+
'must be an array, Series, or dict')
1302+
12841303
else: # pragma: no cover
12851304
raise ValueError("'orient' must be either 'columns' or 'index'")
12861305

pandas/tests/frame/test_constructors.py

+17-3
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,14 @@ def test_constructor_dict(self):
268268

269269
# GH10856
270270
# dict with scalar values should raise error, even if columns passed
271-
with pytest.raises(ValueError):
271+
msg = 'If using all scalar values, you must pass an index'
272+
with tm.assert_raises_regex(ValueError, msg):
272273
DataFrame({'a': 0.7})
273274

274-
with pytest.raises(ValueError):
275+
with tm.assert_raises_regex(ValueError, msg):
275276
DataFrame({'a': 0.7}, columns=['a'])
276277

277-
with pytest.raises(ValueError):
278+
with tm.assert_raises_regex(ValueError, msg):
278279
DataFrame({'a': 0.7}, columns=['b'])
279280

280281
def test_constructor_multi_index(self):
@@ -1204,6 +1205,19 @@ def test_constructor_from_items(self):
12041205
columns=['one', 'two', 'three'])
12051206
tm.assert_frame_equal(rs, xp)
12061207

1208+
def test_constructor_from_items_scalars(self):
1209+
# GH 17312
1210+
with tm.assert_raises_regex(ValueError,
1211+
'The value in each \(key, value\) '
1212+
'pair must be an array, Series, or dict'):
1213+
DataFrame.from_items([('A', 1), ('B', 4)])
1214+
1215+
with tm.assert_raises_regex(ValueError,
1216+
'The value in each \(key, value\) '
1217+
'pair must be an array, Series, or dict'):
1218+
DataFrame.from_items([('A', 1), ('B', 2)], columns=['col1'],
1219+
orient='index')
1220+
12071221
def test_constructor_mix_series_nonseries(self):
12081222
df = DataFrame({'A': self.frame['A'],
12091223
'B': list(self.frame['B'])}, columns=['A', 'B'])

0 commit comments

Comments
 (0)