From f6e376fead6653ed29ea2a89ddadab1b39c5a437 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Tue, 1 Aug 2017 16:33:39 +0200 Subject: [PATCH 1/5] REF: repr - allow block to override values that get formatted --- pandas/core/internals.py | 4 +++ pandas/core/series.py | 6 ++++ pandas/io/formats/format.py | 6 ++-- pandas/tests/test_internals_external_block.py | 28 +++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 pandas/tests/test_internals_external_block.py diff --git a/pandas/core/internals.py b/pandas/core/internals.py index 25c367fcbd968..64ffc89298b70 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -159,6 +159,10 @@ def internal_values(self, dtype=None): """ return self.values + def formatting_values(self): + """Return the internal format used by the DataFrame/SeriesFormatter""" + return self.internal_values() + def get_values(self, dtype=None): """ return an internal format, currently just the ndarray diff --git a/pandas/core/series.py b/pandas/core/series.py index 60d268c89a9d7..292b6f633cdd4 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -398,6 +398,12 @@ def _values(self): """ return the internal repr of this data """ return self._data.internal_values() + def _formatting_values(self): + """Return the values that can be formatted (used by Series and + DataFrameFormatter) + """ + return self._data._block.formatting_values() + def get_values(self): """ same as values (but handles sparseness conversions); is a view """ return self._data.get_values() diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 2b322431bd301..733fd3bd39b52 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -237,7 +237,8 @@ def _get_formatted_index(self): return fmt_index, have_header def _get_formatted_values(self): - return format_array(self.tr_series._values, None, + values_to_format = self.tr_series._formatting_values() + return format_array(values_to_format, None, float_format=self.float_format, na_rep=self.na_rep) def to_string(self): @@ -694,7 +695,8 @@ def to_latex(self, column_format=None, longtable=False, encoding=None, def _format_col(self, i): frame = self.tr_frame formatter = self._get_formatter(i) - return format_array(frame.iloc[:, i]._values, formatter, + values_to_format = frame.iloc[:, i]._formatting_values() + return format_array(values_to_format, formatter, float_format=self.float_format, na_rep=self.na_rep, space=self.col_space, decimal=self.decimal) diff --git a/pandas/tests/test_internals_external_block.py b/pandas/tests/test_internals_external_block.py new file mode 100644 index 0000000000000..b8badcfb8159d --- /dev/null +++ b/pandas/tests/test_internals_external_block.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# pylint: disable=W0102 + +import numpy as np + +import pandas as pd +from pandas.core.internals import Block, BlockManager + + +class CustomBlock(Block): + + def formatting_values(self): + return np.array(["Val: {}".format(i) for i in self.values]) + + +def test_custom_repr(): + values = np.arange(3) + + # series + block = CustomBlock(values, placement=slice(0, 3)) + s = pd.Series(block, index=pd.RangeIndex(3), fastpath=True) + assert repr(s) == '0 Val: 0\n1 Val: 1\n2 Val: 2\ndtype: int64' + + # dataframe + block = CustomBlock(values.reshape(1, -1), placement=slice(0, 1)) + blk_mgr = BlockManager([block], [['col'], range(3)]) + df = pd.DataFrame(blk_mgr) + assert repr(df) == ' col\n0 Val: 0\n1 Val: 1\n2 Val: 2' From ec7ff5d7ed20c5352c7c2bccbee307da1cdd7de6 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Wed, 2 Aug 2017 11:46:13 +0200 Subject: [PATCH 2/5] extra redirect + move tests --- pandas/core/internals.py | 6 +++++- pandas/core/series.py | 6 +++--- pandas/tests/internals/__init__.py | 0 .../test_external_block.py} | 0 pandas/tests/{ => internals}/test_internals.py | 0 5 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 pandas/tests/internals/__init__.py rename pandas/tests/{test_internals_external_block.py => internals/test_external_block.py} (100%) rename pandas/tests/{ => internals}/test_internals.py (100%) diff --git a/pandas/core/internals.py b/pandas/core/internals.py index 64ffc89298b70..880fc7db4b6eb 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -160,7 +160,7 @@ def internal_values(self, dtype=None): return self.values def formatting_values(self): - """Return the internal format used by the DataFrame/SeriesFormatter""" + """Return the internal values used by the DataFrame/SeriesFormatter""" return self.internal_values() def get_values(self, dtype=None): @@ -4320,6 +4320,10 @@ def external_values(self): def internal_values(self): return self._block.internal_values() + def formatting_values(self): + """Return the internal values used by the DataFrame/SeriesFormatter""" + return self._block.formatting_values() + def get_values(self): """ return a dense type view """ return np.array(self._block.to_dense(), copy=False) diff --git a/pandas/core/series.py b/pandas/core/series.py index 292b6f633cdd4..2b852d3b6916c 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -399,10 +399,10 @@ def _values(self): return self._data.internal_values() def _formatting_values(self): - """Return the values that can be formatted (used by Series and - DataFrameFormatter) + """Return the values that can be formatted (used by SeriesFormatter + and DataFrameFormatter) """ - return self._data._block.formatting_values() + return self._data.formatting_values() def get_values(self): """ same as values (but handles sparseness conversions); is a view """ diff --git a/pandas/tests/internals/__init__.py b/pandas/tests/internals/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/pandas/tests/test_internals_external_block.py b/pandas/tests/internals/test_external_block.py similarity index 100% rename from pandas/tests/test_internals_external_block.py rename to pandas/tests/internals/test_external_block.py diff --git a/pandas/tests/test_internals.py b/pandas/tests/internals/test_internals.py similarity index 100% rename from pandas/tests/test_internals.py rename to pandas/tests/internals/test_internals.py From 7e259c93afa228c7b67197cead9e1ea80b1279af Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Wed, 2 Aug 2017 13:51:05 +0200 Subject: [PATCH 3/5] add to setup.py + specify int64 in test --- pandas/tests/internals/test_external_block.py | 2 +- setup.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/tests/internals/test_external_block.py b/pandas/tests/internals/test_external_block.py index b8badcfb8159d..93df92eab2527 100644 --- a/pandas/tests/internals/test_external_block.py +++ b/pandas/tests/internals/test_external_block.py @@ -14,7 +14,7 @@ def formatting_values(self): def test_custom_repr(): - values = np.arange(3) + values = np.arange(3, dtype='int64') # series block = CustomBlock(values, placement=slice(0, 3)) diff --git a/setup.py b/setup.py index d5791862cfb19..a912b25328954 100755 --- a/setup.py +++ b/setup.py @@ -670,6 +670,7 @@ def pxd(name): 'pandas.tests.indexes.datetimes', 'pandas.tests.indexes.timedeltas', 'pandas.tests.indexes.period', + 'pandas.tests.internals', 'pandas.tests.io', 'pandas.tests.io.json', 'pandas.tests.io.parser', From dcd3c0f2abb4b1497319c989cdac22ef94a97422 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 3 Aug 2017 23:47:59 +0200 Subject: [PATCH 4/5] remove usage of fastpath in test example --- pandas/tests/internals/test_external_block.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/tests/internals/test_external_block.py b/pandas/tests/internals/test_external_block.py index 93df92eab2527..01b2bc1a08706 100644 --- a/pandas/tests/internals/test_external_block.py +++ b/pandas/tests/internals/test_external_block.py @@ -4,7 +4,7 @@ import numpy as np import pandas as pd -from pandas.core.internals import Block, BlockManager +from pandas.core.internals import Block, BlockManager, SingleBlockManager class CustomBlock(Block): @@ -18,7 +18,8 @@ def test_custom_repr(): # series block = CustomBlock(values, placement=slice(0, 3)) - s = pd.Series(block, index=pd.RangeIndex(3), fastpath=True) + + s = pd.Series(SingleBlockManager(block, pd.RangeIndex(3))) assert repr(s) == '0 Val: 0\n1 Val: 1\n2 Val: 2\ndtype: int64' # dataframe From b41b713eece90dd8a0de36884d02ddb632ec8b3c Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 3 Aug 2017 23:50:55 +0200 Subject: [PATCH 5/5] pep8 --- pandas/tests/internals/test_external_block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/internals/test_external_block.py b/pandas/tests/internals/test_external_block.py index 01b2bc1a08706..cccde76c3e1d9 100644 --- a/pandas/tests/internals/test_external_block.py +++ b/pandas/tests/internals/test_external_block.py @@ -18,7 +18,7 @@ def test_custom_repr(): # series block = CustomBlock(values, placement=slice(0, 3)) - + s = pd.Series(SingleBlockManager(block, pd.RangeIndex(3))) assert repr(s) == '0 Val: 0\n1 Val: 1\n2 Val: 2\ndtype: int64'