Skip to content

Commit 029d12d

Browse files
author
Chang She
committed
Merge pull request #2409 from changhiskhan/index-format
Index format
2 parents 16becb0 + 25274a9 commit 029d12d

File tree

4 files changed

+72
-86
lines changed

4 files changed

+72
-86
lines changed

pandas/core/format.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ def _get_footer(self):
9999
def _get_formatted_index(self):
100100
index = self.series.index
101101
is_multi = isinstance(index, MultiIndex)
102+
102103
if is_multi:
103104
have_header = any(name for name in index.names)
104105
fmt_index = index.format(names=True)
@@ -391,11 +392,13 @@ def _get_formatted_index(self):
391392
show_index_names = self.show_index_names and self.has_index_names
392393
show_col_names = (self.show_index_names and self.has_column_names)
393394

395+
fmt = self.formatters.get('__index__', None)
394396
if isinstance(index, MultiIndex):
395397
fmt_index = index.format(sparsify=self.sparsify, adjoin=False,
396-
names=show_index_names)
398+
names=show_index_names,
399+
formatter=fmt)
397400
else:
398-
fmt_index = [index.format(name=show_index_names)]
401+
fmt_index = [index.format(name=show_index_names, formatter=fmt)]
399402

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

@@ -622,7 +625,7 @@ def _write_regular_rows(self, fmt_values, indent):
622625

623626
if '__index__' in self.fmt.formatters:
624627
f = self.fmt.formatters['__index__']
625-
index_values = self.frame.index.values.map(f)
628+
index_values = self.frame.index.map(f)
626629
else:
627630
index_values = self.frame.index.format()
628631

pandas/core/index.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -421,15 +421,19 @@ def take(self, indexer, axis=0):
421421
taken = self.view(np.ndarray).take(indexer)
422422
return self._constructor(taken, name=self.name)
423423

424-
def format(self, name=False):
424+
def format(self, name=False, formatter=None):
425425
"""
426426
Render a string representation of the Index
427427
"""
428428
from pandas.core.format import format_array
429429

430430
header = []
431431
if name:
432-
header.append(com.pprint_thing(self.name) if self.name is not None else '')
432+
header.append(com.pprint_thing(self.name)
433+
if self.name is not None else '')
434+
435+
if formatter is not None:
436+
return header + list(self.map(formatter))
433437

434438
if self.is_all_dates:
435439
zero_time = time(0, 0)
@@ -1559,14 +1563,14 @@ def get_level_values(self, level):
15591563
return unique_vals.take(labels)
15601564

15611565
def format(self, space=2, sparsify=None, adjoin=True, names=False,
1562-
na_rep='NaN'):
1566+
na_rep='NaN', formatter=None):
15631567
if len(self) == 0:
15641568
return []
15651569

15661570
stringified_levels = []
15671571
for lev, lab in zip(self.levels, self.labels):
15681572
if len(lev) > 0:
1569-
formatted = lev.take(lab).format()
1573+
formatted = lev.take(lab).format(formatter=formatter)
15701574
else:
15711575
# weird all NA case
15721576
formatted = [com.pprint_thing(x) for x in com.take_1d(lev.values, lab)]

pandas/tests/test_format.py

+53
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,46 @@ def test_to_html_multiindex_sparsify(self):
328328
</table>"""
329329
self.assertEquals(result, expected)
330330

331+
def test_to_html_index_formatter(self):
332+
df = DataFrame([[0, 1], [2, 3], [4, 5], [6, 7]],
333+
columns=['foo', None], index=range(4))
334+
335+
f = lambda x: 'abcd'[x]
336+
result = df.to_html(formatters={'__index__': f})
337+
expected = """\
338+
<table border="1" class="dataframe">
339+
<thead>
340+
<tr style="text-align: right;">
341+
<th></th>
342+
<th>foo</th>
343+
<th></th>
344+
</tr>
345+
</thead>
346+
<tbody>
347+
<tr>
348+
<td><strong>a</strong></td>
349+
<td> 0</td>
350+
<td> 1</td>
351+
</tr>
352+
<tr>
353+
<td><strong>b</strong></td>
354+
<td> 2</td>
355+
<td> 3</td>
356+
</tr>
357+
<tr>
358+
<td><strong>c</strong></td>
359+
<td> 4</td>
360+
<td> 5</td>
361+
</tr>
362+
<tr>
363+
<td><strong>d</strong></td>
364+
<td> 6</td>
365+
<td> 7</td>
366+
</tr>
367+
</tbody>
368+
</table>"""
369+
self.assertEquals(result, expected)
370+
331371

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

582+
def test_to_string_index_formatter(self):
583+
df = DataFrame([range(5), range(5, 10), range(10, 15)])
584+
585+
rs = df.to_string(formatters={'__index__': lambda x: 'abc'[x]})
586+
587+
xp = """\
588+
0 1 2 3 4
589+
a 0 1 2 3 4
590+
b 5 6 7 8 9
591+
c 10 11 12 13 14\
592+
"""
593+
self.assertEqual(rs, xp)
594+
542595
def test_to_string_left_justify_cols(self):
543596
fmt.reset_printoptions()
544597
df = DataFrame({'x' : [3234, 0.253]})

pandas/tests/test_panel4d.py

+5-79
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ def wrapper(x):
145145

146146
class SafeForSparse(object):
147147

148+
_multiprocess_can_split_ = True
149+
148150
@classmethod
149151
def assert_panel_equal(cls, x, y):
150152
assert_panel_equal(x, y)
@@ -193,37 +195,6 @@ def test_get_axis_name(self):
193195
self.assertEqual(self.panel4d._get_axis_name(2), 'major_axis')
194196
self.assertEqual(self.panel4d._get_axis_name(3), 'minor_axis')
195197

196-
#def test_get_plane_axes(self):
197-
# # what to do here?
198-
199-
# index, columns = self.panel._get_plane_axes('items')
200-
# index, columns = self.panel._get_plane_axes('major_axis')
201-
# index, columns = self.panel._get_plane_axes('minor_axis')
202-
# index, columns = self.panel._get_plane_axes(0)
203-
204-
def test_truncate(self):
205-
raise nose.SkipTest
206-
207-
#dates = self.panel.major_axis
208-
#start, end = dates[1], dates[5]
209-
210-
#trunced = self.panel.truncate(start, end, axis='major')
211-
#expected = self.panel['ItemA'].truncate(start, end)
212-
213-
#assert_frame_equal(trunced['ItemA'], expected)
214-
215-
#trunced = self.panel.truncate(before=start, axis='major')
216-
#expected = self.panel['ItemA'].truncate(before=start)
217-
218-
#assert_frame_equal(trunced['ItemA'], expected)
219-
220-
#trunced = self.panel.truncate(after=end, axis='major')
221-
#expected = self.panel['ItemA'].truncate(after=end)
222-
223-
#assert_frame_equal(trunced['ItemA'], expected)
224-
225-
# XXX test other axes
226-
227198
def test_arith(self):
228199
self._test_op(self.panel4d, operator.add)
229200
self._test_op(self.panel4d, operator.sub)
@@ -317,6 +288,7 @@ def test_abs(self):
317288

318289
class CheckIndexing(object):
319290

291+
_multiprocess_can_split_ = True
320292

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

399-
def test_setitem_ndarray(self):
400-
raise nose.SkipTest
401-
# from pandas import DateRange, datetools
402-
403-
# timeidx = DateRange(start=datetime(2009,1,1),
404-
# end=datetime(2009,12,31),
405-
# offset=datetools.MonthEnd())
406-
# lons_coarse = np.linspace(-177.5, 177.5, 72)
407-
# lats_coarse = np.linspace(-87.5, 87.5, 36)
408-
# P = Panel(items=timeidx, major_axis=lons_coarse, minor_axis=lats_coarse)
409-
# data = np.random.randn(72*36).reshape((72,36))
410-
# key = datetime(2009,2,28)
411-
# P[key] = data#
412-
413-
# assert_almost_equal(P[key].values, data)
414-
415371
def test_major_xs(self):
416372
ref = self.panel4d['l1']['ItemA']
417373

@@ -514,38 +470,6 @@ def test_getitem_fancy_xs(self):
514470
#self.assertRaises(NotImplementedError, self.panel4d.major_xs)
515471
#self.assertRaises(NotImplementedError, self.panel4d.minor_xs)
516472

517-
def test_getitem_fancy_xs_check_view(self):
518-
raise nose.SkipTest
519-
# item = 'ItemB'
520-
# date = self.panel.major_axis[5]
521-
# col = 'C'
522-
523-
# # make sure it's always a view
524-
# NS = slice(None, None)
525-
526-
# # DataFrames
527-
# comp = assert_frame_equal
528-
# self._check_view(item, comp)
529-
# self._check_view((item, NS), comp)
530-
# self._check_view((item, NS, NS), comp)
531-
# self._check_view((NS, date), comp)
532-
# self._check_view((NS, date, NS), comp)
533-
# self._check_view((NS, NS, 'C'), comp)
534-
535-
# # Series
536-
# comp = assert_series_equal
537-
# self._check_view((item, date), comp)
538-
# self._check_view((item, date, NS), comp)
539-
# self._check_view((item, NS, 'C'), comp)
540-
# self._check_view((NS, date, 'C'), comp)#
541-
542-
#def _check_view(self, indexer, comp):
543-
# cp = self.panel.copy()
544-
# obj = cp.ix[indexer]
545-
# obj.values[:] = 0
546-
# self.assert_((obj.values == 0).all())
547-
# comp(cp.ix[indexer].reindex_like(obj), obj)
548-
549473
def test_get_value(self):
550474
for label in self.panel4d.labels:
551475
for item in self.panel4d.items:
@@ -574,6 +498,8 @@ def test_set_value(self):
574498

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

501+
_multiprocess_can_split_ = True
502+
577503
@classmethod
578504
def assert_panel4d_equal(cls,x, y):
579505
assert_panel4d_equal(x, y)

0 commit comments

Comments
 (0)