diff --git a/doc/source/whatsnew/v0.18.0.txt b/doc/source/whatsnew/v0.18.0.txt
index b3bbc5cf5ef8c..71cf61c8f8f82 100644
--- a/doc/source/whatsnew/v0.18.0.txt
+++ b/doc/source/whatsnew/v0.18.0.txt
@@ -867,6 +867,9 @@ Other API Changes
- Statistical functions for ``NDFrame`` objects will now raise if non-numpy-compatible arguments are passed in for ``**kwargs`` (:issue:`12301`)
+- ``.to_latex`` and ``.to_html`` gain a ``decimal`` parameter like ``.to_csv``, default ``'.'`` (:issue:`12031`)
+
+
.. _whatsnew_0180.deprecations:
Deprecations
diff --git a/pandas/core/format.py b/pandas/core/format.py
index d5b95abb6ad08..101a5e64b65b5 100644
--- a/pandas/core/format.py
+++ b/pandas/core/format.py
@@ -338,7 +338,7 @@ 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, **kwds):
+ max_cols=None, show_dimensions=False, decimal='.', **kwds):
self.frame = frame
self.buf = _expand_user(buf) if buf is not None else StringIO()
self.show_index_names = index_names
@@ -351,6 +351,7 @@ def __init__(self, frame, buf=None, columns=None, col_space=None,
self.float_format = float_format
self.formatters = formatters if formatters is not None else {}
self.na_rep = na_rep
+ self.decimal = decimal
self.col_space = col_space
self.header = header
self.index = index
@@ -648,7 +649,7 @@ def _format_col(self, i):
formatter = self._get_formatter(i)
return format_array(frame.iloc[:, i]._values, formatter,
float_format=self.float_format, na_rep=self.na_rep,
- space=self.col_space)
+ space=self.col_space, decimal=self.decimal)
def to_html(self, classes=None, notebook=False):
"""
@@ -1970,7 +1971,7 @@ def get_formatted_cells(self):
def format_array(values, formatter, float_format=None, na_rep='NaN',
- digits=None, space=None, justify='right'):
+ digits=None, space=None, justify='right', decimal='.'):
if com.is_categorical_dtype(values):
fmt_klass = CategoricalArrayFormatter
@@ -2000,7 +2001,7 @@ def format_array(values, formatter, float_format=None, na_rep='NaN',
fmt_obj = fmt_klass(values, digits=digits, na_rep=na_rep,
float_format=float_format, formatter=formatter,
- space=space, justify=justify)
+ space=space, justify=justify, decimal=decimal)
return fmt_obj.get_result()
diff --git a/pandas/core/frame.py b/pandas/core/frame.py
index cd32ff2133cae..449068eff4f43 100644
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -1497,7 +1497,7 @@ def to_html(self, buf=None, columns=None, col_space=None, colSpace=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):
+ notebook=False, decimal='.'):
"""
Render a DataFrame as an HTML table.
@@ -1515,7 +1515,10 @@ def to_html(self, buf=None, columns=None, col_space=None, colSpace=None,
max_cols : int, optional
Maximum number of columns to show before truncating. If None, show
all.
+ decimal : string, default '.'
+ Character recognized as decimal separator, e.g. ',' in Europe
+ .. versionadded:: 0.18.0
"""
if colSpace is not None: # pragma: no cover
@@ -1533,7 +1536,8 @@ def to_html(self, buf=None, columns=None, col_space=None, colSpace=None,
bold_rows=bold_rows, escape=escape,
max_rows=max_rows,
max_cols=max_cols,
- show_dimensions=show_dimensions)
+ show_dimensions=show_dimensions,
+ decimal=decimal)
# TODO: a generic formatter wld b in DataFrameFormatter
formatter.to_html(classes=classes, notebook=notebook)
@@ -1545,7 +1549,7 @@ def to_latex(self, buf=None, columns=None, col_space=None, colSpace=None,
header=True, index=True, na_rep='NaN', formatters=None,
float_format=None, sparsify=None, index_names=True,
bold_rows=True, column_format=None, longtable=None,
- escape=None, encoding=None):
+ escape=None, encoding=None, decimal='.'):
"""
Render a DataFrame to a tabular environment table. You can splice
this into a LaTeX document. Requires \\usepackage{booktabs}.
@@ -1568,6 +1572,11 @@ def to_latex(self, buf=None, columns=None, col_space=None, colSpace=None,
characters in column names.
encoding : str, default None
Default encoding is ascii in Python 2 and utf-8 in Python 3
+ decimal : string, default '.'
+ Character recognized as decimal separator, e.g. ',' in Europe
+
+ .. versionadded:: 0.18.0
+
"""
if colSpace is not None: # pragma: no cover
@@ -1588,7 +1597,7 @@ def to_latex(self, buf=None, columns=None, col_space=None, colSpace=None,
bold_rows=bold_rows,
sparsify=sparsify,
index_names=index_names,
- escape=escape)
+ escape=escape, decimal=decimal)
formatter.to_latex(column_format=column_format, longtable=longtable,
encoding=encoding)
diff --git a/pandas/tests/test_format.py b/pandas/tests/test_format.py
index cb5241c205d03..6772c1ee4b1ee 100644
--- a/pandas/tests/test_format.py
+++ b/pandas/tests/test_format.py
@@ -760,6 +760,34 @@ def test_to_html_unicode(self):
expected = u'
\n \n \n | \n A | \n
\n \n \n \n 0 | \n \u03c3 | \n
\n \n
'
self.assertEqual(df.to_html(), expected)
+ def test_to_html_decimal(self):
+ # GH 12031
+ df = DataFrame({'A': [6.0, 3.1, 2.2]})
+ result = df.to_html(decimal=',')
+ expected = ('\n'
+ ' \n'
+ ' \n'
+ ' | \n'
+ ' A | \n'
+ '
\n'
+ ' \n'
+ ' \n'
+ ' \n'
+ ' 0 | \n'
+ ' 6,0 | \n'
+ '
\n'
+ ' \n'
+ ' 1 | \n'
+ ' 3,1 | \n'
+ '
\n'
+ ' \n'
+ ' 2 | \n'
+ ' 2,2 | \n'
+ '
\n'
+ ' \n'
+ '
')
+ self.assertEqual(result, expected)
+
def test_to_html_escaped(self):
a = 'str