Skip to content

Index format #2409

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 2 commits into from
Dec 3, 2012
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
9 changes: 6 additions & 3 deletions pandas/core/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def _get_footer(self):
def _get_formatted_index(self):
index = self.series.index
is_multi = isinstance(index, MultiIndex)

if is_multi:
have_header = any(name for name in index.names)
fmt_index = index.format(names=True)
Expand Down Expand Up @@ -391,11 +392,13 @@ def _get_formatted_index(self):
show_index_names = self.show_index_names and self.has_index_names
show_col_names = (self.show_index_names and self.has_column_names)

fmt = self.formatters.get('__index__', None)
if isinstance(index, MultiIndex):
fmt_index = index.format(sparsify=self.sparsify, adjoin=False,
names=show_index_names)
names=show_index_names,
formatter=fmt)
else:
fmt_index = [index.format(name=show_index_names)]
fmt_index = [index.format(name=show_index_names, formatter=fmt)]

adjoined = adjoin(1, *fmt_index).split('\n')

Expand Down Expand Up @@ -622,7 +625,7 @@ def _write_regular_rows(self, fmt_values, indent):

if '__index__' in self.fmt.formatters:
f = self.fmt.formatters['__index__']
index_values = self.frame.index.values.map(f)
index_values = self.frame.index.map(f)
else:
index_values = self.frame.index.format()

Expand Down
12 changes: 8 additions & 4 deletions pandas/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,15 +421,19 @@ def take(self, indexer, axis=0):
taken = self.view(np.ndarray).take(indexer)
return self._constructor(taken, name=self.name)

def format(self, name=False):
def format(self, name=False, formatter=None):
"""
Render a string representation of the Index
"""
from pandas.core.format import format_array

header = []
if name:
header.append(com.pprint_thing(self.name) if self.name is not None else '')
header.append(com.pprint_thing(self.name)
if self.name is not None else '')

if formatter is not None:
return header + list(self.map(formatter))

if self.is_all_dates:
zero_time = time(0, 0)
Expand Down Expand Up @@ -1559,14 +1563,14 @@ def get_level_values(self, level):
return unique_vals.take(labels)

def format(self, space=2, sparsify=None, adjoin=True, names=False,
na_rep='NaN'):
na_rep='NaN', formatter=None):
if len(self) == 0:
return []

stringified_levels = []
for lev, lab in zip(self.levels, self.labels):
if len(lev) > 0:
formatted = lev.take(lab).format()
formatted = lev.take(lab).format(formatter=formatter)
else:
# weird all NA case
formatted = [com.pprint_thing(x) for x in com.take_1d(lev.values, lab)]
Expand Down
53 changes: 53 additions & 0 deletions pandas/tests/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,46 @@ def test_to_html_multiindex_sparsify(self):
</table>"""
self.assertEquals(result, expected)

def test_to_html_index_formatter(self):
df = DataFrame([[0, 1], [2, 3], [4, 5], [6, 7]],
columns=['foo', None], index=range(4))

f = lambda x: 'abcd'[x]
result = df.to_html(formatters={'__index__': f})
expected = """\
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>foo</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>a</strong></td>
<td> 0</td>
<td> 1</td>
</tr>
<tr>
<td><strong>b</strong></td>
<td> 2</td>
<td> 3</td>
</tr>
<tr>
<td><strong>c</strong></td>
<td> 4</td>
<td> 5</td>
</tr>
<tr>
<td><strong>d</strong></td>
<td> 6</td>
<td> 7</td>
</tr>
</tbody>
</table>"""
self.assertEquals(result, expected)


def test_nonunicode_nonascii_alignment(self):
df = DataFrame([["aa\xc3\xa4\xc3\xa4", 1], ["bbbb", 2]])
Expand Down Expand Up @@ -539,6 +579,19 @@ def test_to_string_int_formatting(self):
'3 -35')
self.assertEqual(output, expected)

def test_to_string_index_formatter(self):
df = DataFrame([range(5), range(5, 10), range(10, 15)])

rs = df.to_string(formatters={'__index__': lambda x: 'abc'[x]})

xp = """\
0 1 2 3 4
a 0 1 2 3 4
b 5 6 7 8 9
c 10 11 12 13 14\
"""
self.assertEqual(rs, xp)

def test_to_string_left_justify_cols(self):
fmt.reset_printoptions()
df = DataFrame({'x' : [3234, 0.253]})
Expand Down
84 changes: 5 additions & 79 deletions pandas/tests/test_panel4d.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ def wrapper(x):

class SafeForSparse(object):

_multiprocess_can_split_ = True

@classmethod
def assert_panel_equal(cls, x, y):
assert_panel_equal(x, y)
Expand Down Expand Up @@ -193,37 +195,6 @@ def test_get_axis_name(self):
self.assertEqual(self.panel4d._get_axis_name(2), 'major_axis')
self.assertEqual(self.panel4d._get_axis_name(3), 'minor_axis')

#def test_get_plane_axes(self):
# # what to do here?

# index, columns = self.panel._get_plane_axes('items')
# index, columns = self.panel._get_plane_axes('major_axis')
# index, columns = self.panel._get_plane_axes('minor_axis')
# index, columns = self.panel._get_plane_axes(0)

def test_truncate(self):
raise nose.SkipTest

#dates = self.panel.major_axis
#start, end = dates[1], dates[5]

#trunced = self.panel.truncate(start, end, axis='major')
#expected = self.panel['ItemA'].truncate(start, end)

#assert_frame_equal(trunced['ItemA'], expected)

#trunced = self.panel.truncate(before=start, axis='major')
#expected = self.panel['ItemA'].truncate(before=start)

#assert_frame_equal(trunced['ItemA'], expected)

#trunced = self.panel.truncate(after=end, axis='major')
#expected = self.panel['ItemA'].truncate(after=end)

#assert_frame_equal(trunced['ItemA'], expected)

# XXX test other axes

def test_arith(self):
self._test_op(self.panel4d, operator.add)
self._test_op(self.panel4d, operator.sub)
Expand Down Expand Up @@ -317,6 +288,7 @@ def test_abs(self):

class CheckIndexing(object):

_multiprocess_can_split_ = True

def test_getitem(self):
self.assertRaises(Exception, self.panel4d.__getitem__, 'ItemQ')
Expand Down Expand Up @@ -396,22 +368,6 @@ def test_setitem(self):
self.panel4d['lP'] = self.panel4d['l1'] > 0
self.assert_(self.panel4d['lP'].values.dtype == np.bool_)

def test_setitem_ndarray(self):
raise nose.SkipTest
# from pandas import DateRange, datetools

# timeidx = DateRange(start=datetime(2009,1,1),
# end=datetime(2009,12,31),
# offset=datetools.MonthEnd())
# lons_coarse = np.linspace(-177.5, 177.5, 72)
# lats_coarse = np.linspace(-87.5, 87.5, 36)
# P = Panel(items=timeidx, major_axis=lons_coarse, minor_axis=lats_coarse)
# data = np.random.randn(72*36).reshape((72,36))
# key = datetime(2009,2,28)
# P[key] = data#

# assert_almost_equal(P[key].values, data)

def test_major_xs(self):
ref = self.panel4d['l1']['ItemA']

Expand Down Expand Up @@ -514,38 +470,6 @@ def test_getitem_fancy_xs(self):
#self.assertRaises(NotImplementedError, self.panel4d.major_xs)
#self.assertRaises(NotImplementedError, self.panel4d.minor_xs)

def test_getitem_fancy_xs_check_view(self):
raise nose.SkipTest
# item = 'ItemB'
# date = self.panel.major_axis[5]
# col = 'C'

# # make sure it's always a view
# NS = slice(None, None)

# # DataFrames
# comp = assert_frame_equal
# self._check_view(item, comp)
# self._check_view((item, NS), comp)
# self._check_view((item, NS, NS), comp)
# self._check_view((NS, date), comp)
# self._check_view((NS, date, NS), comp)
# self._check_view((NS, NS, 'C'), comp)

# # Series
# comp = assert_series_equal
# self._check_view((item, date), comp)
# self._check_view((item, date, NS), comp)
# self._check_view((item, NS, 'C'), comp)
# self._check_view((NS, date, 'C'), comp)#

#def _check_view(self, indexer, comp):
# cp = self.panel.copy()
# obj = cp.ix[indexer]
# obj.values[:] = 0
# self.assert_((obj.values == 0).all())
# comp(cp.ix[indexer].reindex_like(obj), obj)

def test_get_value(self):
for label in self.panel4d.labels:
for item in self.panel4d.items:
Expand Down Expand Up @@ -574,6 +498,8 @@ def test_set_value(self):

class TestPanel4d(unittest.TestCase, CheckIndexing, SafeForSparse, SafeForLongAndSparse):

_multiprocess_can_split_ = True

@classmethod
def assert_panel4d_equal(cls,x, y):
assert_panel4d_equal(x, y)
Expand Down