Skip to content

Commit eecf160

Browse files
committed
Merge pull request pandas-dev#8668 from waveform80/deque-concat
BUG: fix concat to work with more iterables (GH8645)
2 parents ff6b98a + 8836589 commit eecf160

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

doc/source/whatsnew/v0.15.1.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,28 @@ API changes
7575

7676
gr.apply(sum)
7777

78+
- ``concat`` permits a wider variety of iterables of pandas objects to be
79+
passed as the first parameter (:issue:`8645`):
80+
81+
.. ipython:: python
82+
83+
from collections import deque
84+
df1 = pd.DataFrame([1, 2, 3])
85+
df2 = pd.DataFrame([4, 5, 6])
86+
87+
previous behavior:
88+
89+
.. code-block:: python
90+
91+
In [7]: pd.concat(deque((df1, df2)))
92+
TypeError: first argument must be a list-like of pandas objects, you passed an object of type "deque"
93+
94+
current behavior:
95+
96+
.. ipython:: python
97+
98+
pd.concat(deque((df1, df2)))
99+
78100
.. _whatsnew_0151.enhancements:
79101

80102
Enhancements

pandas/tools/merge.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ def concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
675675
676676
Parameters
677677
----------
678-
objs : list or dict of Series, DataFrame, or Panel objects
678+
objs : a sequence or mapping of Series, DataFrame, or Panel objects
679679
If a dict is passed, the sorted keys will be used as the `keys`
680680
argument, unless it is passed, in which case the values will be
681681
selected (see below). Any None objects will be dropped silently unless
@@ -731,8 +731,8 @@ class _Concatenator(object):
731731
def __init__(self, objs, axis=0, join='outer', join_axes=None,
732732
keys=None, levels=None, names=None,
733733
ignore_index=False, verify_integrity=False, copy=True):
734-
if not isinstance(objs, (list,tuple,types.GeneratorType,dict,TextFileReader)):
735-
raise TypeError('first argument must be a list-like of pandas '
734+
if isinstance(objs, (NDFrame, compat.string_types)):
735+
raise TypeError('first argument must be an iterable of pandas '
736736
'objects, you passed an object of type '
737737
'"{0}"'.format(type(objs).__name__))
738738

pandas/tools/tests/test_merge.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,33 @@ def test_concat_series_axis1_same_names_ignore_index(self):
22032203
result = concat([s1, s2], axis=1, ignore_index=True)
22042204
self.assertTrue(np.array_equal(result.columns, [0, 1]))
22052205

2206+
def test_concat_iterables(self):
2207+
from collections import deque, Iterable
2208+
2209+
# GH8645 check concat works with tuples, list, generators, and weird
2210+
# stuff like deque and custom iterables
2211+
df1 = DataFrame([1, 2, 3])
2212+
df2 = DataFrame([4, 5, 6])
2213+
expected = DataFrame([1, 2, 3, 4, 5, 6])
2214+
assert_frame_equal(pd.concat((df1, df2), ignore_index=True), expected)
2215+
assert_frame_equal(pd.concat([df1, df2], ignore_index=True), expected)
2216+
assert_frame_equal(pd.concat((df for df in (df1, df2)), ignore_index=True), expected)
2217+
assert_frame_equal(pd.concat(deque((df1, df2)), ignore_index=True), expected)
2218+
class CustomIterator1(object):
2219+
def __len__(self):
2220+
return 2
2221+
def __getitem__(self, index):
2222+
try:
2223+
return {0: df1, 1: df2}[index]
2224+
except KeyError:
2225+
raise IndexError
2226+
assert_frame_equal(pd.concat(CustomIterator1(), ignore_index=True), expected)
2227+
class CustomIterator2(Iterable):
2228+
def __iter__(self):
2229+
yield df1
2230+
yield df2
2231+
assert_frame_equal(pd.concat(CustomIterator2(), ignore_index=True), expected)
2232+
22062233
def test_concat_invalid(self):
22072234

22082235
# trying to concat a ndframe with a non-ndframe

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy