Skip to content

Commit 4fb3b38

Browse files
committed
allow using Iterable in Series and DataFrame constructor
1 parent 322dbf4 commit 4fb3b38

File tree

4 files changed

+36
-21
lines changed

4 files changed

+36
-21
lines changed

pandas/core/frame.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import collections
1717
import itertools
1818
import sys
19-
import types
2019
import warnings
2120
from textwrap import dedent
2221

@@ -75,7 +74,8 @@
7574
from pandas.core.arrays import Categorical, ExtensionArray
7675
import pandas.core.algorithms as algorithms
7776
from pandas.compat import (range, map, zip, lrange, lmap, lzip, StringIO, u,
78-
OrderedDict, raise_with_traceback)
77+
OrderedDict, raise_with_traceback,
78+
string_and_binary_types)
7979
from pandas import compat
8080
from pandas.compat import PY36
8181
from pandas.compat.numpy import function as nv
@@ -390,8 +390,9 @@ def __init__(self, data=None, index=None, columns=None, dtype=None,
390390
else:
391391
mgr = self._init_ndarray(data, index, columns, dtype=dtype,
392392
copy=copy)
393-
elif isinstance(data, (list, types.GeneratorType)):
394-
if isinstance(data, types.GeneratorType):
393+
elif (isinstance(data, collections.Iterable)
394+
and not isinstance(data, string_and_binary_types)):
395+
if not isinstance(data, collections.Sequence):
395396
data = list(data)
396397
if len(data) > 0:
397398
if is_list_like(data[0]) and getattr(data[0], 'ndim', 1) == 1:
@@ -416,8 +417,6 @@ def __init__(self, data=None, index=None, columns=None, dtype=None,
416417
copy=copy)
417418
else:
418419
mgr = self._init_dict({}, index, columns, dtype=dtype)
419-
elif isinstance(data, collections.Iterator):
420-
raise TypeError("data argument can't be an iterator")
421420
else:
422421
try:
423422
arr = np.array(data, dtype=dtype, copy=copy)

pandas/core/series.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# pylint: disable=E1101,E1103
77
# pylint: disable=W0703,W0622,W0613,W0201
88

9-
import types
9+
import collections
1010
import warnings
1111
from textwrap import dedent
1212

@@ -238,12 +238,12 @@ def __init__(self, data=None, index=None, dtype=None, name=None,
238238

239239
elif is_extension_array_dtype(data):
240240
pass
241-
elif (isinstance(data, types.GeneratorType) or
242-
(compat.PY3 and isinstance(data, map))):
243-
data = list(data)
244241
elif isinstance(data, (set, frozenset)):
245242
raise TypeError("{0!r} type is unordered"
246243
"".format(data.__class__.__name__))
244+
elif (isinstance(data, collections.Iterable)
245+
and not isinstance(data, collections.Sized)):
246+
data = list(data)
247247
else:
248248

249249
# handle sparse passed here (and force conversion)

pandas/tests/frame/test_constructors.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -865,12 +865,6 @@ def test_constructor_more(self):
865865
dm = DataFrame(index=np.arange(10))
866866
assert dm.values.shape == (10, 0)
867867

868-
# corner, silly
869-
# TODO: Fix this Exception to be better...
870-
with tm.assert_raises_regex(ValueError, 'constructor not '
871-
'properly called'):
872-
DataFrame((1, 2, 3))
873-
874868
# can't cast
875869
mat = np.array(['foo', 'bar'], dtype=object).reshape(2, 1)
876870
with tm.assert_raises_regex(ValueError, 'cast'):
@@ -953,6 +947,16 @@ def __len__(self, n):
953947
array.array('i', range(10))])
954948
tm.assert_frame_equal(result, expected, check_dtype=False)
955949

950+
def test_constructor_iterable(self):
951+
class Iter():
952+
def __iter__(self):
953+
for i in range(10):
954+
yield [1, 2, 3]
955+
956+
expected = DataFrame([[1, 2, 3]] * 10)
957+
result = DataFrame(Iter())
958+
tm.assert_frame_equal(result, expected)
959+
956960
def test_constructor_iterator(self):
957961

958962
expected = DataFrame([list(range(10)), list(range(10))])
@@ -1374,10 +1378,6 @@ def test_constructor_miscast_na_int_dtype(self):
13741378
expected = DataFrame([[np.nan, 1], [1, 0]])
13751379
tm.assert_frame_equal(df, expected)
13761380

1377-
def test_constructor_iterator_failure(self):
1378-
with tm.assert_raises_regex(TypeError, 'iterator'):
1379-
DataFrame(iter([1, 2, 3]))
1380-
13811381
def test_constructor_column_duplicates(self):
13821382
# it works! #2079
13831383
df = DataFrame([[8, 5]], columns=['a', 'a'])

pandas/tests/series/test_constructors.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,28 @@ def test_constructor_series(self):
156156

157157
assert_series_equal(s2, s1.sort_index())
158158

159-
def test_constructor_iterator(self):
159+
def test_constructor_iterable(self):
160+
class Iter():
161+
def __iter__(self):
162+
for i in range(10):
163+
yield i
164+
165+
expected = Series(list(range(10)), dtype='int64')
166+
result = Series(Iter(), dtype='int64')
167+
assert_series_equal(result, expected)
168+
169+
def test_constructor_sequence(self):
160170

161171
expected = Series(list(range(10)), dtype='int64')
162172
result = Series(range(10), dtype='int64')
163173
assert_series_equal(result, expected)
164174

175+
def test_constructor_single_str(self):
176+
177+
expected = Series(['abc'])
178+
result = Series('abc')
179+
assert_series_equal(result, expected)
180+
165181
def test_constructor_list_like(self):
166182

167183
# make sure that we are coercing different

0 commit comments

Comments
 (0)