Skip to content

BUG: inconsisten panel indexing with aligning frame (GH7763) #8399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 26, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,13 @@ def _align_series(self, indexer, ser):
def _align_frame(self, indexer, df):
is_frame = self.obj.ndim == 2
is_panel = self.obj.ndim >= 3

if isinstance(indexer, tuple):

aligners = [not _is_null_slice(idx) for idx in indexer]
sum_aligners = sum(aligners)
single_aligner = sum_aligners == 1

idx, cols = None, None
sindexers = []
for i, ix in enumerate(indexer):
Expand All @@ -626,13 +632,21 @@ def _align_frame(self, indexer, df):

# panel
if is_panel:
if len(sindexers) == 1 and idx is None and cols is None:
if sindexers[0] == 0:
df = df.T
return self.obj.conform(df, axis=sindexers[0])
df = df.T

# need to conform to the convention
# as we are not selecting on the items axis
# and we have a single indexer
# GH 7763
if len(sindexers) == 1 and sindexers[0] != 0:
df = df.T

if idx is None:
idx = df.index
if cols is None:
cols = df.columns

if idx is not None and cols is not None:

if df.index.equals(idx) and df.columns.equals(cols):
val = df.copy().values
else:
Expand All @@ -655,21 +669,15 @@ def _align_frame(self, indexer, df):
val = df.reindex(index=ax).values
return val

elif np.isscalar(indexer) and not is_frame:
elif np.isscalar(indexer) and is_panel:
idx = self.obj.axes[1]
cols = self.obj.axes[2]

# by definition we are indexing on the 0th axis
if is_panel:
df = df.T

if idx.equals(df.index) and cols.equals(df.columns):
return df.copy().values

# a passed in dataframe which is actually a transpose
# of what is needed
elif idx.equals(df.columns) and cols.equals(df.index):
return df.T.copy().values
if idx.equals(df.index) and cols.equals(df.columns):
return df.copy().values

return df.reindex(idx, columns=cols).values

Expand Down
27 changes: 27 additions & 0 deletions pandas/tests/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2291,6 +2291,33 @@ def test_panel_getitem(self):
test1 = panel.ix[:, "2002"]
tm.assert_panel_equal(test1,test2)

def test_panel_setitem(self):

# GH 7763
# loc and setitem have setting differences
np.random.seed(0)
index=range(3)
columns = list('abc')

panel = Panel({'A' : DataFrame(np.random.randn(3, 3), index=index, columns=columns),
'B' : DataFrame(np.random.randn(3, 3), index=index, columns=columns),
'C' : DataFrame(np.random.randn(3, 3), index=index, columns=columns)
})

replace = DataFrame(np.eye(3,3), index=range(3), columns=columns)
expected = Panel({ 'A' : replace, 'B' : replace, 'C' : replace })

p = panel.copy()
for idx in list('ABC'):
p[idx] = replace
tm.assert_panel_equal(p, expected)

p = panel.copy()
for idx in list('ABC'):
p.loc[idx,:,:] = replace
tm.assert_panel_equal(p, expected)


def test_panel_assignment(self):

# GH3777
Expand Down
34 changes: 26 additions & 8 deletions pandas/tests/test_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,24 +668,42 @@ def test_ix_align(self):

def test_ix_frame_align(self):
from pandas import DataFrame
df = DataFrame(np.random.randn(2, 10))
df.sort_index(inplace=True)
p_orig = Panel(np.random.randn(3, 10, 2))
p_orig = tm.makePanel()
df = p_orig.ix[0].copy()
assert_frame_equal(p_orig['ItemA'],df)

p = p_orig.copy()
p.ix[0, :, :] = df
out = p.ix[0, :, :].T.reindex(df.index, columns=df.columns)
assert_frame_equal(out, df)
assert_panel_equal(p, p_orig)

p = p_orig.copy()
p.ix[0] = df
out = p.ix[0].T.reindex(df.index, columns=df.columns)
assert_frame_equal(out, df)
assert_panel_equal(p, p_orig)

p = p_orig.copy()
p.iloc[0, :, :] = df
assert_panel_equal(p, p_orig)

p = p_orig.copy()
p.iloc[0] = df
assert_panel_equal(p, p_orig)

p = p_orig.copy()
p.loc['ItemA'] = df
assert_panel_equal(p, p_orig)

p = p_orig.copy()
p.loc['ItemA', :, :] = df
assert_panel_equal(p, p_orig)

p = p_orig.copy()
p['ItemA'] = df
assert_panel_equal(p, p_orig)

p = p_orig.copy()
p.ix[0, [0, 1, 3, 5], -2:] = df
out = p.ix[0, [0, 1, 3, 5], -2:]
assert_frame_equal(out, df.T.reindex([0, 1, 3, 5], p.minor_axis[-2:]))
assert_frame_equal(out, df.iloc[[0,1,3,5],[2,3]])

# GH3830, panel assignent by values/frame
for dtype in ['float64','int64']:
Expand Down