diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst
index 9275357e5ad18..7c98da440e1bf 100644
--- a/doc/source/whatsnew/v0.24.0.rst
+++ b/doc/source/whatsnew/v0.24.0.rst
@@ -1319,6 +1319,7 @@ Notice how we now instead output ``np.nan`` itself instead of a stringified form
- :func:`read_sas()` will correctly parse sas7bdat files with many columns (:issue:`22628`)
- :func:`read_sas()` will correctly parse sas7bdat files with data page types having also bit 7 set (so page type is 128 + 256 = 384) (:issue:`16615`)
- Bug in :meth:`detect_client_encoding` where potential ``IOError`` goes unhandled when importing in a mod_wsgi process due to restricted access to stdout. (:issue:`21552`)
+- Bug in :func:`to_html()` with ``index=False`` misses truncation indicators (...) on truncated DataFrame (:issue:`15019`, :issue:`22783`)
- Bug in :func:`DataFrame.to_string()` that broke column alignment when ``index=False`` and width of first column's values is greater than the width of first column's header (:issue:`16839`, :issue:`13032`)
- Bug in :func:`DataFrame.to_string()` that caused representations of :class:`DataFrame` to not take up the whole window (:issue:`22984`)
- Bug in :func:`DataFrame.to_csv` where a single level MultiIndex incorrectly wrote a tuple. Now just the value of the index is written (:issue:`19589`).
diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py
index 2a2a3e57729ec..967e5fca5f711 100644
--- a/pandas/io/formats/html.py
+++ b/pandas/io/formats/html.py
@@ -305,6 +305,8 @@ def _column_header():
align = self.fmt.justify
if truncate_h:
+ if not self.fmt.index:
+ row_levels = 0
ins_col = row_levels + self.fmt.tr_col_num
col_row.insert(ins_col, '...')
@@ -336,15 +338,10 @@ def _write_body(self, indent):
fmt_values[i] = self.fmt._format_col(i)
# write values
- if self.fmt.index:
- if isinstance(self.frame.index, ABCMultiIndex):
- self._write_hierarchical_rows(fmt_values, indent)
- else:
- self._write_regular_rows(fmt_values, indent)
+ if self.fmt.index and isinstance(self.frame.index, ABCMultiIndex):
+ self._write_hierarchical_rows(fmt_values, indent)
else:
- for i in range(min(len(self.frame), self.max_rows)):
- row = [fmt_values[j][i] for j in range(len(self.columns))]
- self.write_tr(row, indent, self.indent_delta, tags=None)
+ self._write_regular_rows(fmt_values, indent)
indent -= self.indent_delta
self.write('', indent)
@@ -358,11 +355,16 @@ def _write_regular_rows(self, fmt_values, indent):
ncols = len(self.fmt.tr_frame.columns)
nrows = len(self.fmt.tr_frame)
- fmt = self.fmt._get_formatter('__index__')
- if fmt is not None:
- index_values = self.fmt.tr_frame.index.map(fmt)
+
+ if self.fmt.index:
+ fmt = self.fmt._get_formatter('__index__')
+ if fmt is not None:
+ index_values = self.fmt.tr_frame.index.map(fmt)
+ else:
+ index_values = self.fmt.tr_frame.index.format()
+ row_levels = 1
else:
- index_values = self.fmt.tr_frame.index.format()
+ row_levels = 0
row = []
for i in range(nrows):
@@ -370,17 +372,18 @@ def _write_regular_rows(self, fmt_values, indent):
if truncate_v and i == (self.fmt.tr_row_num):
str_sep_row = ['...'] * len(row)
self.write_tr(str_sep_row, indent, self.indent_delta,
- tags=None, nindex_levels=1)
+ tags=None, nindex_levels=row_levels)
row = []
- row.append(index_values[i])
+ if self.fmt.index:
+ row.append(index_values[i])
row.extend(fmt_values[j][i] for j in range(ncols))
if truncate_h:
- dot_col_ix = self.fmt.tr_col_num + 1
+ dot_col_ix = self.fmt.tr_col_num + row_levels
row.insert(dot_col_ix, '...')
self.write_tr(row, indent, self.indent_delta, tags=None,
- nindex_levels=1)
+ nindex_levels=row_levels)
def _write_hierarchical_rows(self, fmt_values, indent):
template = 'rowspan="{span}" valign="top"'
diff --git a/pandas/tests/io/formats/data/gh15019_expected_output.html b/pandas/tests/io/formats/data/gh15019_expected_output.html
new file mode 100644
index 0000000000000..5fb9d960f4465
--- /dev/null
+++ b/pandas/tests/io/formats/data/gh15019_expected_output.html
@@ -0,0 +1,30 @@
+
+
+
+ 0 |
+ 1 |
+
+
+
+
+ 1.764052 |
+ 0.400157 |
+
+
+ 0.978738 |
+ 2.240893 |
+
+
+ ... |
+ ... |
+
+
+ 0.950088 |
+ -0.151357 |
+
+
+ -0.103219 |
+ 0.410599 |
+
+
+
diff --git a/pandas/tests/io/formats/data/gh22783_expected_output.html b/pandas/tests/io/formats/data/gh22783_expected_output.html
new file mode 100644
index 0000000000000..107db43c48639
--- /dev/null
+++ b/pandas/tests/io/formats/data/gh22783_expected_output.html
@@ -0,0 +1,27 @@
+
+
+
+ 0 |
+ 1 |
+ ... |
+ 3 |
+ 4 |
+
+
+
+
+ 1.764052 |
+ 0.400157 |
+ ... |
+ 2.240893 |
+ 1.867558 |
+
+
+ -0.977278 |
+ 0.950088 |
+ ... |
+ -0.103219 |
+ 0.410599 |
+
+
+
diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py
index 0416cf6da7912..32cf21ddf5f38 100644
--- a/pandas/tests/io/formats/test_to_html.py
+++ b/pandas/tests/io/formats/test_to_html.py
@@ -22,6 +22,28 @@
pass
+def expected_html(datapath, name):
+ """
+ Read HTML file from formats data directory.
+
+ Parameters
+ ----------
+ datapath : pytest fixture
+ The datapath fixture injected into a test by pytest.
+ name : str
+ The name of the HTML file without the suffix.
+
+ Returns
+ -------
+ str : contents of HTML file.
+ """
+ filename = '.'.join([name, 'html'])
+ filepath = datapath('io', 'formats', 'data', filename)
+ with open(filepath) as f:
+ html = f.read()
+ return html.rstrip()
+
+
class TestToHTML(object):
def test_to_html_with_col_space(self):
@@ -1881,6 +1903,29 @@ def test_to_html_multiindex_max_cols(self):
""")
assert result == expected
+ @pytest.mark.parametrize('index', [False, 0])
+ def test_to_html_truncation_index_false_max_rows(self, datapath, index):
+ # GH 15019
+ data = [[1.764052, 0.400157],
+ [0.978738, 2.240893],
+ [1.867558, -0.977278],
+ [0.950088, -0.151357],
+ [-0.103219, 0.410599]]
+ df = pd.DataFrame(data)
+ result = df.to_html(max_rows=4, index=index)
+ expected = expected_html(datapath, 'gh15019_expected_output')
+ assert result == expected
+
+ @pytest.mark.parametrize('index', [False, 0])
+ def test_to_html_truncation_index_false_max_cols(self, datapath, index):
+ # GH 22783
+ data = [[1.764052, 0.400157, 0.978738, 2.240893, 1.867558],
+ [-0.977278, 0.950088, -0.151357, -0.103219, 0.410599]]
+ df = pd.DataFrame(data)
+ result = df.to_html(max_cols=4, index=index)
+ expected = expected_html(datapath, 'gh22783_expected_output')
+ assert result == expected
+
def test_to_html_notebook_has_style(self):
df = pd.DataFrame({"A": [1, 2, 3]})
result = df.to_html(notebook=True)