Skip to content

Commit b134121

Browse files
committed
BUG: allow DataFrame constructor to accept more list-like objects, e.g. list of
`ollections.Sequence and array.Array objects (GH3783 and GH42971)
1 parent d20d9bf commit b134121

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

doc/source/release.rst

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ Improvements to existing features
113113
``io.excel.xls.writer``. (:issue:`4745`, :issue:`4750`)
114114
- ``Panel.to_excel()`` now accepts keyword arguments that will be passed to
115115
its ``DataFrame``'s ``to_excel()`` methods. (:issue:`4750`)
116+
- allow DataFrame constructor to accept more list-like objects, e.g. list of
117+
``collections.Sequence`` and ``array.Array`` objects (:issue:`3783`,:issue:`42971`)
116118

117119
API Changes
118120
~~~~~~~~~~~

pandas/core/frame.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from pandas.core.common import (isnull, notnull, PandasError, _try_sort,
2525
_default_index, _maybe_upcast, _is_sequence,
2626
_infer_dtype_from_scalar, _values_from_object,
27-
_coerce_to_dtypes, _DATELIKE_DTYPES)
27+
_coerce_to_dtypes, _DATELIKE_DTYPES, is_list_like)
2828
from pandas.core.generic import NDFrame
2929
from pandas.core.index import Index, MultiIndex, _ensure_index
3030
from pandas.core.indexing import (_NDFrameIndexer, _maybe_droplevels,
@@ -418,7 +418,7 @@ def __init__(self, data=None, index=None, columns=None, dtype=None,
418418
if index is None and isinstance(data[0], Series):
419419
index = _get_names_from_index(data)
420420

421-
if isinstance(data[0], (list, tuple, collections.Mapping, Series)):
421+
if is_list_like(data[0]) and getattr(data[0],'ndim',0) <= 1:
422422
arrays, columns = _to_arrays(data, columns, dtype=dtype)
423423
columns = _ensure_index(columns)
424424

@@ -4545,7 +4545,7 @@ def isin(self, values, iloc=False):
45454545

45464546

45474547
else:
4548-
if not com.is_list_like(values):
4548+
if not is_list_like(values):
45494549
raise TypeError("only list-like or dict-like objects are"
45504550
" allowed to be passed to DataFrame.isin(), "
45514551
"you passed a "
@@ -4705,7 +4705,7 @@ def extract_index(data):
47054705
elif isinstance(v, dict):
47064706
have_dicts = True
47074707
indexes.append(list(v.keys()))
4708-
elif isinstance(v, (list, tuple, np.ndarray)):
4708+
elif is_list_like(v) and getattr(v,'ndim',0) <= 1:
47094709
have_raw_arrays = True
47104710
raw_lengths.append(len(v))
47114711

pandas/tests/test_frame.py

+26
Original file line numberDiff line numberDiff line change
@@ -2606,6 +2606,32 @@ def test_constructor_list_of_lists(self):
26062606
self.assert_(com.is_integer_dtype(df['num']))
26072607
self.assert_(df['str'].dtype == np.object_)
26082608

2609+
def test_constructor_sequence_like(self):
2610+
# GH 3783
2611+
# collections.Squence like
2612+
import collections
2613+
2614+
class DummyContainer(collections.Sequence):
2615+
def __init__(self, lst):
2616+
self._lst = lst
2617+
def __getitem__(self, n):
2618+
return self._lst.__getitem__(n)
2619+
def __len__(self, n):
2620+
return self._lst.__len__()
2621+
2622+
l = [DummyContainer([1, 'a']), DummyContainer([2, 'b'])]
2623+
columns = ["num", "str"]
2624+
result = DataFrame(l, columns=columns)
2625+
expected = DataFrame([[1,'a'],[2,'b']],columns=columns)
2626+
assert_frame_equal(result, expected, check_dtype=False)
2627+
2628+
# GH 4297
2629+
# support Array
2630+
import array
2631+
result = DataFrame.from_items([('A', array.array('i', range(10)))])
2632+
expected = DataFrame({ 'A' : list(range(10)) })
2633+
assert_frame_equal(result, expected, check_dtype=False)
2634+
26092635
def test_constructor_list_of_dicts(self):
26102636
data = [OrderedDict([['a', 1.5], ['b', 3], ['c', 4], ['d', 6]]),
26112637
OrderedDict([['a', 1.5], ['b', 3], ['d', 6]]),

0 commit comments

Comments
 (0)