diff --git a/doc/source/options.rst b/doc/source/options.rst index 25f03df4040a3..77cac6d495d13 100644 --- a/doc/source/options.rst +++ b/doc/source/options.rst @@ -392,6 +392,9 @@ display.width 80 Width of the display in characters. IPython qtconsole, or IDLE do not run in a terminal and hence it is not possible to correctly detect the width. +html.border 1 A ``border=value`` attribute is + inserted in the ```` tag + for the DataFrame HTML repr. io.excel.xls.writer xlwt The default Excel writer engine for 'xls' files. io.excel.xlsm.writer openpyxl The default Excel writer engine for diff --git a/doc/source/whatsnew/v0.19.0.txt b/doc/source/whatsnew/v0.19.0.txt index 45cdd23140487..b4e53eec6bbce 100644 --- a/doc/source/whatsnew/v0.19.0.txt +++ b/doc/source/whatsnew/v0.19.0.txt @@ -426,6 +426,7 @@ Other enhancements df.sort_values(by='row2', axis=1) - Added documentation to :ref:`I/O` regarding the perils of reading in columns with mixed dtypes and how to handle it (:issue:`13746`) +- :meth:`~DataFrame.to_html` now has a ``border`` argument to control the value in the opening ``
`` tag. The default is the value of the ``html.border`` option, which defaults to 1. This also affects the notebook HTML repr, but since Jupyter's CSS includes a border-width attribute, the visual effect is the same. (:issue:`11563`). - Raise ``ImportError`` in the sql functions when ``sqlalchemy`` is not installed and a connection string is used (:issue:`11920`). - Compatibility with matplotlib 2.0. Older versions of pandas should also work with matplotlib 2.0 (:issue:`13333`) diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 5cbc968f06fa7..fe47391c9ff81 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -346,6 +346,17 @@ def mpl_style_cb(key): cf.deprecate_option('display.height', msg=pc_height_deprecation_warning, rkey='display.max_rows') +pc_html_border_doc = """ +: int + A ``border=value`` attribute is inserted in the ``
`` tag + for the DataFrame HTML repr. +""" + +with cf.config_prefix('html'): + cf.register_option('border', 1, pc_html_border_doc, + validator=is_int) + + tc_sim_interactive_doc = """ : boolean Whether to simulate interactive mode for purposes of testing diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 205af5c805877..676997ede28b4 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1560,7 +1560,8 @@ def to_html(self, buf=None, columns=None, col_space=None, header=True, index=True, na_rep='NaN', formatters=None, float_format=None, sparsify=None, index_names=True, justify=None, bold_rows=True, classes=None, escape=True, max_rows=None, max_cols=None, - show_dimensions=False, notebook=False, decimal='.'): + show_dimensions=False, notebook=False, decimal='.', + border=None): """ Render a DataFrame as an HTML table. @@ -1582,6 +1583,11 @@ def to_html(self, buf=None, columns=None, col_space=None, header=True, Character recognized as decimal separator, e.g. ',' in Europe .. versionadded:: 0.18.0 + border : int + A ``border=border`` attribute is included in the opening + `
` tag. Default ``pd.options.html.border``. + + .. versionadded:: 0.19.0 """ formatter = fmt.DataFrameFormatter(self, buf=buf, columns=columns, @@ -1597,7 +1603,7 @@ def to_html(self, buf=None, columns=None, col_space=None, header=True, show_dimensions=show_dimensions, decimal=decimal) # TODO: a generic formatter wld b in DataFrameFormatter - formatter.to_html(classes=classes, notebook=notebook) + formatter.to_html(classes=classes, notebook=notebook, border=border) if buf is None: return formatter.buf.getvalue() diff --git a/pandas/formats/format.py b/pandas/formats/format.py index b83e3c4e73fdb..6a361d17cf578 100644 --- a/pandas/formats/format.py +++ b/pandas/formats/format.py @@ -670,20 +670,28 @@ def _format_col(self, i): float_format=self.float_format, na_rep=self.na_rep, space=self.col_space, decimal=self.decimal) - def to_html(self, classes=None, notebook=False): + def to_html(self, classes=None, notebook=False, border=None): """ Render a DataFrame to a html table. Parameters ---------- + classes : str or list-like + classes to include in the `class` attribute of the opening + ``
`` tag, in addition to the default "dataframe". notebook : {True, False}, optional, default False Whether the generated HTML is for IPython Notebook. + border : int + A ``border=border`` attribute is included in the opening + ``
`` tag. Default ``pd.options.html.border``. - """ + .. versionadded:: 0.19.0 + """ html_renderer = HTMLFormatter(self, classes=classes, max_rows=self.max_rows, max_cols=self.max_cols, - notebook=notebook) + notebook=notebook, + border=border) if hasattr(self.buf, 'write'): html_renderer.write_result(self.buf) elif isinstance(self.buf, compat.string_types): @@ -909,7 +917,7 @@ class HTMLFormatter(TableFormatter): indent_delta = 2 def __init__(self, formatter, classes=None, max_rows=None, max_cols=None, - notebook=False): + notebook=False, border=None): self.fmt = formatter self.classes = classes @@ -925,6 +933,9 @@ def __init__(self, formatter, classes=None, max_rows=None, max_cols=None, self.is_truncated = (self.max_rows < len(self.fmt.frame) or self.max_cols < len(self.fmt.columns)) self.notebook = notebook + if border is None: + border = get_option('html.border') + self.border = border def write(self, s, indent=0): rs = pprint_thing(s) @@ -1000,7 +1011,8 @@ def write_result(self, buf): self.write(''.format(div_style)) - self.write('
' % ' '.join(_classes), + self.write('
' % (self.border, + ' '.join(_classes)), indent) indent += self.indent_delta diff --git a/pandas/tests/formats/test_format.py b/pandas/tests/formats/test_format.py index e6147737e9a1d..0a2e63a018799 100644 --- a/pandas/tests/formats/test_format.py +++ b/pandas/tests/formats/test_format.py @@ -1650,6 +1650,23 @@ def test_to_html_truncate_multi_index_sparse_off(self): expected = expected.decode('utf-8') self.assertEqual(result, expected) + def test_to_html_border(self): + df = DataFrame({'A': [1, 2]}) + result = df.to_html() + assert 'border="1"' in result + + def test_to_html_border_option(self): + df = DataFrame({'A': [1, 2]}) + with pd.option_context('html.border', 0): + result = df.to_html() + self.assertTrue('border="0"' in result) + self.assertTrue('border="0"' in df._repr_html_()) + + def test_to_html_border_zero(self): + df = DataFrame({'A': [1, 2]}) + result = df.to_html(border=0) + self.assertTrue('border="0"' in result) + def test_nonunicode_nonascii_alignment(self): df = DataFrame([["aa\xc3\xa4\xc3\xa4", 1], ["bbbb", 2]]) rep_str = df.to_string()