Repository: statsmodels/statsmodels

Issue:
Summary.as_latex() produces invalid LaTeX for variable names containing underscore
With statsmodels 0.6.1:
- Use the example from the [index page of the documentation](http://statsmodels.sourceforge.net/stable/).
- Change the variable `Literacy` to `Crime_prop`.
- Call the `as_latex()` method of the summary object.

``` python
import numpy as np
import statsmodels.api as sm
import statsmodels.formula.api as smf

# Load data
dat = sm.datasets.get_rdataset("Guerry", "HistData").data

# Fit regression model (using the natural log of one of the regressors)
results = smf.ols('Lottery ~ Crime_prop + np.log(Pop1831)', data=dat).fit()

# Inspect the results
print(results.summary().as_latex())
```

The output contains the line:

``` latex
\textbf{Crime_prop}      &       0.0029  &        0.001     &     3.887  &         0.000        &         0.001     0.004       \\
```

This is invalid LaTeX, because the underscore (`_`) is not set in math mode or escaped (`\_`).



Discussion:
How can I fix this?


Resolving patch:
diff --git a/statsmodels/iolib/table.py b/statsmodels/iolib/table.py
--- a/statsmodels/iolib/table.py
+++ b/statsmodels/iolib/table.py
@@ -716,7 +716,7 @@ def format(self, width, output_format='txt', **fmt_dict):
         elif datatype in fmt:
             if "replacements" in fmt:
                 if isinstance(data, str):
-                    for repl in fmt["replacements"]:
+                    for repl in sorted(fmt["replacements"]):
                         data = data.replace(repl, fmt["replacements"][repl])
 
             dfmt = fmt.get(datatype)
@@ -878,7 +878,8 @@ def set_datatype(self, val):
     stub=r'\textbf{%s}',
     empty='',
     missing='--',
-    replacements={"%" : "\%", ">" : "$>$", "|" : "$|$"}
+    #replacements will be processed in lexicographical order
+    replacements={"#" : "\#", "$" : "\$", "%" : "\%", "&" : "\&", ">" : "$>$", "_" : "\_", "|" : "$|$"} 
 )
 
 default_fmts = dict(


Test patch:
diff --git a/statsmodels/iolib/tests/test_table.py b/statsmodels/iolib/tests/test_table.py
--- a/statsmodels/iolib/tests/test_table.py
+++ b/statsmodels/iolib/tests/test_table.py
@@ -164,6 +164,31 @@ def test_html_fmt1(self):
         test_txt_fmt1(self)
         test_ltx_fmt1(self)
         test_html_fmt1(self)
+    def test_SimpleTable_special_chars(self):
+    # Simple table with characters: (%, >, |, _, $, &, #)
+        cell0c_data = 22
+        cell1c_data = 1053
+        row0c_data = [cell0c_data, cell1c_data]
+        row1c_data = [23, 6250.4]
+        table1c_data = [ row0c_data, row1c_data ]
+        test1c_stubs = ('>stub1%', 'stub_2')
+        test1c_header = ('#header1$', 'header&|')
+        tbl_c = SimpleTable(table1c_data, test1c_header, test1c_stubs, ltx_fmt=ltx_fmt1)
+        def test_ltx_special_chars(self):
+        # Test for special characters (latex) in headers and stubs
+            desired = r"""
+\begin{tabular}{lcc}
+\toprule
+                    & \textbf{\#header1\$} & \textbf{header\&$|$}  \\
+\midrule
+\textbf{$>$stub1\%} &          22          &         1053          \\
+\textbf{stub\_2}    &          23          &        6250.4         \\
+\bottomrule
+\end{tabular}
+"""
+            actual = '\n%s\n' % tbl_c.as_latex_tabular(center=False)
+            self.assertEqual(actual, desired)
+        test_ltx_special_chars(self)
     def test_regression_with_tuples(self):
         i = pandas.Series( [1,2,3,4]*10 , name="i")
         y = pandas.Series( [1,2,3,4,5]*8, name="y")