Skip to content

Commit ab9898c

Browse files
committed
BUG: handle list of Series properly, close #792
1 parent d068bcc commit ab9898c

File tree

4 files changed

+72
-13
lines changed

4 files changed

+72
-13
lines changed

pandas/core/frame.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,12 +298,16 @@ def __init__(self, data=None, index=None, columns=None, dtype=None,
298298
copy=copy)
299299
elif isinstance(data, list):
300300
if len(data) > 0:
301-
if isinstance(data[0], (list, tuple)):
302-
data, columns = _list_to_sdict(data, columns)
303-
mgr = self._init_dict(data, index, columns, dtype=dtype)
304-
elif isinstance(data[0], dict):
305-
data, columns = _list_of_dict_to_sdict(data, columns)
306-
mgr = self._init_dict(data, index, columns, dtype=dtype)
301+
if isinstance(data[0], (list, tuple, dict, Series)):
302+
conv_data, columns = _to_sdict(data, columns)
303+
if isinstance(conv_data, dict):
304+
if len(conv_data) == 0 and index is None:
305+
index = np.arange(len(data))
306+
mgr = self._init_dict(conv_data, index, columns,
307+
dtype=dtype)
308+
else:
309+
mgr = self._init_ndarray(conv_data, index, columns,
310+
dtype=dtype, copy=copy)
307311
else:
308312
mgr = self._init_ndarray(data, index, columns, dtype=dtype,
309313
copy=copy)
@@ -4040,6 +4044,16 @@ def _rec_to_dict(arr):
40404044
return columns, sdict
40414045

40424046

4047+
def _to_sdict(data, columns):
4048+
if isinstance(data[0], (list, tuple)):
4049+
return _list_to_sdict(data, columns)
4050+
elif isinstance(data[0], dict):
4051+
return _list_of_dict_to_sdict(data, columns)
4052+
elif isinstance(data[0], Series):
4053+
return _list_of_series_to_sdict(data, columns)
4054+
else: # pragma: no cover
4055+
raise TypeError('No logic to handle %s type' % type(data[0]))
4056+
40434057
def _list_to_sdict(data, columns):
40444058
if len(data) > 0 and isinstance(data[0], tuple):
40454059
content = list(lib.to_object_array_tuples(data).T)
@@ -4052,6 +4066,20 @@ def _list_to_sdict(data, columns):
40524066
return {}, columns
40534067
return _convert_object_array(content, columns)
40544068

4069+
def _list_of_series_to_sdict(data, columns):
4070+
from pandas.core.index import _get_combined_index
4071+
4072+
if columns is None:
4073+
columns = _get_combined_index([s.index for s in data])
4074+
4075+
values = np.vstack([s.reindex(columns, copy=False).values
4076+
for s in data])
4077+
4078+
if values.dtype == np.object_:
4079+
content = list(values.T)
4080+
return _convert_object_array(content, columns)
4081+
else:
4082+
return values, columns
40554083

40564084
def _list_of_dict_to_sdict(data, columns):
40574085
if columns is None:

pandas/core/panel.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ def panel_index(time, panels, names=['time', 'panel']):
6060
>>> panels = ['A', 'B', 'C']
6161
>>> panel_idx = panel_index(years, panels)
6262
>>> panel_idx
63-
MultiIndex([(1960, 'A'), (1961, 'A'), (1962, 'A'), (1960, 'B'), (1961, 'B'),
64-
(1962, 'B'), (1960, 'C'), (1961, 'C'), (1962, 'C')], dtype=object)
63+
MultiIndex([(1960, 'A'), (1961, 'A'), (1962, 'A'), (1960, 'B'),
64+
(1961, 'B'), (1962, 'B'), (1960, 'C'), (1961, 'C'),
65+
(1962, 'C')], dtype=object)
6566
6667
or
6768
@@ -70,8 +71,9 @@ def panel_index(time, panels, names=['time', 'panel']):
7071
>>> panels = np.tile(['A', 'B', 'C'], 3)
7172
>>> panel_idx = panel_index(years, panels)
7273
>>> panel_idx
73-
MultiIndex([(1960, 'A'), (1960, 'B'), (1960, 'C'), (1961, 'A'), (1961, 'B'),
74-
(1961, 'C'), (1962, 'A'), (1962, 'B'), (1962, 'C')], dtype=object)
74+
MultiIndex([(1960, 'A'), (1960, 'B'), (1960, 'C'), (1961, 'A'),
75+
(1961, 'B'), (1961, 'C'), (1962, 'A'), (1962, 'B'),
76+
(1962, 'C')], dtype=object)
7577
"""
7678
time, panels = _ensure_like_indices(time, panels)
7779
time_factor = Factor(time)
@@ -458,12 +460,12 @@ def to_sparse(self, fill_value=None, kind='block'):
458460

459461
def to_excel(self, path, na_rep=''):
460462
"""
461-
Write each DataFrame in Panel to a separate excel sheet
463+
Write each DataFrame in Panel to a separate excel sheet
462464
463465
Parameters
464466
----------
465467
excel_writer : string or ExcelWriter object
466-
File path or existing ExcelWriter
468+
File path or existing ExcelWriter
467469
na_rep : string, default ''
468470
Missing data rep'n
469471
"""

pandas/tests/test_frame.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1505,9 +1505,31 @@ def test_constructor_list_of_dicts(self):
15051505
assert_frame_equal(result, expected.reindex(result.index))
15061506

15071507
result = DataFrame([{}])
1508-
expected = DataFrame([])
1508+
expected = DataFrame(index=[0])
15091509
assert_frame_equal(result, expected)
15101510

1511+
def test_constructor_list_of_series(self):
1512+
data = [{'a': 1.5, 'b': 3, 'c':4, 'd':6},
1513+
{'a': 1.5, 'b': 3, 'd':6},
1514+
{'a': 1.5, 'd':6},
1515+
{},
1516+
{'a': 1.5, 'b': 3, 'c':4},
1517+
{'b': 3, 'c':4, 'd':6}]
1518+
data = [Series(d) for d in data]
1519+
1520+
result = DataFrame(data)
1521+
expected = DataFrame.from_dict(dict(zip(range(len(data)), data)),
1522+
orient='index')
1523+
assert_frame_equal(result, expected.reindex(result.index))
1524+
1525+
result2 = DataFrame(data, index=np.arange(6))
1526+
assert_frame_equal(result, result2)
1527+
1528+
result = DataFrame([Series({})])
1529+
expected = DataFrame(index=[0])
1530+
assert_frame_equal(result, expected)
1531+
1532+
15111533
def test_constructor_ragged(self):
15121534
data = {'A' : randn(10),
15131535
'B' : randn(8)}

vb_suite/groupby.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,10 @@ def f():
9191
'value2' : 'var',
9292
'value3' : 'sum'})""",
9393
setup, start_date=datetime(2011, 9, 1))
94+
95+
groupby_multi_different_numpy_functions = \
96+
Benchmark("""df.groupby(['key1', 'key2']).agg({'value1' : np.mean,
97+
'value2' : np.var,
98+
'value3' : np.sum})""",
99+
setup, start_date=datetime(2011, 9, 1))
100+

0 commit comments

Comments
 (0)