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()