diff --git a/pandas/core/frame.py b/pandas/core/frame.py
index 28923f0fbf240..32595e6a12ce2 100644
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -19,6 +19,7 @@
import types
import warnings
from textwrap import dedent
+from uuid import uuid1
import numpy as np
import numpy.ma as ma
@@ -674,9 +675,11 @@ def _repr_html_(self):
max_rows = get_option("display.max_rows")
max_cols = get_option("display.max_columns")
show_dimensions = get_option("display.show_dimensions")
+ unique_id = str(uuid1())
return self.to_html(max_rows=max_rows, max_cols=max_cols,
- show_dimensions=show_dimensions, notebook=True)
+ show_dimensions=show_dimensions, notebook=True,
+ table_id=unique_id)
else:
return None
@@ -1727,7 +1730,7 @@ def to_html(self, buf=None, columns=None, col_space=None, header=True,
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='.',
- border=None):
+ border=None, table_id=None):
"""
Render a DataFrame as an HTML table.
@@ -1755,6 +1758,12 @@ def to_html(self, buf=None, columns=None, col_space=None, header=True,
`
` tag. Default ``pd.options.html.border``.
.. versionadded:: 0.19.0
+
+ table_id : str, optional
+ A css id is included in the opening `` tag if specified.
+
+ .. versionadded:: 0.23.0
+
"""
if (justify is not None and
@@ -1772,7 +1781,7 @@ def to_html(self, buf=None, columns=None, col_space=None, header=True,
max_rows=max_rows,
max_cols=max_cols,
show_dimensions=show_dimensions,
- decimal=decimal)
+ decimal=decimal, table_id=table_id)
# TODO: a generic formatter wld b in DataFrameFormatter
formatter.to_html(classes=classes, notebook=notebook, border=border)
diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py
index 269c81b380b5e..5d4ba2dfd37dc 100644
--- a/pandas/io/formats/format.py
+++ b/pandas/io/formats/format.py
@@ -77,7 +77,11 @@
index_names : bool, optional
Prints the names of the indexes, default True
line_width : int, optional
- Width to wrap a line in characters, default no wrap"""
+ Width to wrap a line in characters, default no wrap
+ table_id : str, optional
+ id for the element create by to_html
+
+ .. versionadded:: 0.23.0"""
_VALID_JUSTIFY_PARAMETERS = ("left", "right", "center", "justify",
"justify-all", "start", "end", "inherit",
@@ -387,7 +391,8 @@ def __init__(self, frame, buf=None, columns=None, col_space=None,
header=True, index=True, na_rep='NaN', formatters=None,
justify=None, float_format=None, sparsify=None,
index_names=True, line_width=None, max_rows=None,
- max_cols=None, show_dimensions=False, decimal='.', **kwds):
+ max_cols=None, show_dimensions=False, decimal='.',
+ table_id=None, **kwds):
self.frame = frame
if buf is not None:
self.buf = _expand_user(_stringify_path(buf))
@@ -413,6 +418,7 @@ def __init__(self, frame, buf=None, columns=None, col_space=None,
self.max_rows_displayed = min(max_rows or len(self.frame),
len(self.frame))
self.show_dimensions = show_dimensions
+ self.table_id = table_id
if justify is None:
self.justify = get_option("display.colheader_justify")
@@ -740,7 +746,8 @@ def to_html(self, classes=None, notebook=False, border=None):
max_rows=self.max_rows,
max_cols=self.max_cols,
notebook=notebook,
- border=border)
+ border=border,
+ table_id = self.table_id)
if hasattr(self.buf, 'write'):
html_renderer.write_result(self.buf)
elif isinstance(self.buf, compat.string_types):
@@ -1082,7 +1089,7 @@ class HTMLFormatter(TableFormatter):
indent_delta = 2
def __init__(self, formatter, classes=None, max_rows=None, max_cols=None,
- notebook=False, border=None):
+ notebook=False, border=None, table_id=None):
self.fmt = formatter
self.classes = classes
@@ -1101,6 +1108,7 @@ def __init__(self, formatter, classes=None, max_rows=None, max_cols=None,
if border is None:
border = get_option('display.html.border')
self.border = border
+ self.table_id = table_id
def write(self, s, indent=0):
rs = pprint_thing(s)
@@ -1220,8 +1228,11 @@ def write_result(self, buf):
self.write(''.format(style=div_style))
self.write_style()
- self.write('
'
- .format(border=self.border, cls=' '.join(_classes)), indent)
+ id_section = ' id="{table_id}"'.format(table_id=self.table_id)\
+ if self.table_id is not None else ""
+ self.write(''
+ .format(border=self.border, cls=' '.join(_classes),
+ id_section=id_section), indent)
indent += self.indent_delta
indent = self._write_header(indent)
diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py
index e0ce27de5c31f..24cfd8128a3f7 100644
--- a/pandas/tests/io/formats/test_format.py
+++ b/pandas/tests/io/formats/test_format.py
@@ -1491,8 +1491,9 @@ def test_repr_html_float(self):
'A': np.arange(1, 1 + h),
'B': np.arange(41, 41 + h)}).set_index('idx')
reg_repr = df._repr_html_()
+ print (reg_repr)
assert '..' not in reg_repr
- assert str(40 + h) in reg_repr
+ assert '{num} | '.format(num=str(40 + h)) in reg_repr
h = max_rows + 1
df = DataFrame({'idx': np.linspace(-10, 10, h),
@@ -1500,7 +1501,7 @@ def test_repr_html_float(self):
'B': np.arange(41, 41 + h)}).set_index('idx')
long_repr = df._repr_html_()
assert '..' in long_repr
- assert '31' not in long_repr
+ assert '{num} | '.format(num='31') not in long_repr
assert u('{h} rows ').format(h=h) in long_repr
assert u('2 columns') in long_repr
diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py
index 9e063c2d176e1..5058540283a56 100644
--- a/pandas/tests/io/formats/test_to_html.py
+++ b/pandas/tests/io/formats/test_to_html.py
@@ -1864,3 +1864,11 @@ def test_to_html_with_index_names_false(self):
name='myindexname'))
result = df.to_html(index_names=False)
assert 'myindexname' not in result
+
+ def test_to_html_with_id(self):
+ # gh-8496
+ df = pd.DataFrame({"A": [1, 2]}, index=pd.Index(['a', 'b'],
+ name='myindexname'))
+ result = df.to_html(index_names=False, table_id="TEST_ID")
+ assert ' id="TEST_ID"' in result
+