[openpyxl] pandas.DataFrame.to_excelとかでIllegalCharacterErrorが出たときの対処法

# 前提条件
* Python3.5
* Pandas0.19.1
* openpyxl2.4.1

# 今回対処したい問題
```python
import pandas
target_df = pandas.DataFrame(所与のデータ)
```
で、このデータフレームをExcelファイルに出力しようとすると、

```python
---------------------------------------------------------------------------
IllegalCharacterError                     Traceback (most recent call last)
<ipython-input-88-d629d1ba2e9a> in <module>()
      1 # subset_df = subset_df.applymap(illegal_char_remover)
      2 
----> 3 subset_df.to_excel("./test.xlsx")

/Users/noname/.pyenv/versions/3.5.2/lib/python3.5/site-packages/pandas/core/frame.py in to_excel(self, excel_writer, sheet_name, na_rep, float_format, columns, header, index, index_label, startrow, startcol, engine, merge_cells, encoding, inf_rep, verbose)
   1462         formatted_cells = formatter.get_formatted_cells()
   1463         excel_writer.write_cells(formatted_cells, sheet_name,
-> 1464                                  startrow=startrow, startcol=startcol)
   1465         if need_save:
   1466             excel_writer.save()

/Users/noname/.pyenv/versions/3.5.2/lib/python3.5/site-packages/pandas/io/excel.py in write_cells(self, cells, sheet_name, startrow, startcol)
   1313                 column=startcol + cell.col + 1
   1314             )
-> 1315             xcell.value = _conv_value(cell.val)
   1316 
   1317             style_kwargs = {}

/Users/noname/.pyenv/versions/3.5.2/lib/python3.5/site-packages/openpyxl/cell/cell.py in value(self, value)
    290     def value(self, value):
    291         """Set the value and infer type and display options."""
--> 292         self._bind_value(value)
    293 
    294     @property

/Users/noname/.pyenv/versions/3.5.2/lib/python3.5/site-packages/openpyxl/cell/cell.py in _bind_value(self, value)
    189 
    190         elif isinstance(value, STRING_TYPES):
--> 191             value = self.check_string(value)
    192             self.data_type = self.TYPE_STRING
    193             if len(value) > 1 and value.startswith("="):

/Users/noname/.pyenv/versions/3.5.2/lib/python3.5/site-packages/openpyxl/cell/cell.py in check_string(self, value)
    154         value = value[:32767]
    155         if next(ILLEGAL_CHARACTERS_RE.finditer(value), None):
--> 156             raise IllegalCharacterError
    157         return value
    158 

IllegalCharacterError: 
```
と、怒られてしまうという問題。
検索しても対処法は載っていなかったので、投稿します。

# 対処法
以下のように、openpyxlの中で、IllegalCharacterが定義されている。(https://bitbucket.org/openpyxl/openpyxl/src/dad834128adcb5ca4330bd2bc4bc714b54ccfbb9/openpyxl/cell/cell.py?at=default&fileviewer=file-view-defaultのLine69)

```python
ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')
```
ので、このIllegalCharacterをデータフレームから取り除いてやればよさそう。

```python
import re

# ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')
ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]|[\x00-\x1f\x7f-\x9f]|[\uffff]')
def illegal_char_remover(data):
    """Remove ILLEGAL CHARACTER."""
    if isinstance(data, str):
        return ILLEGAL_CHARACTERS_RE.sub("", data)
    else:
        return data

target_df = target_df.applymap(illegal_char_remover)
```
で、取り除けば、このエラーは起こらなくなる。

# 今回の落ち(解消済み)
\uffffを削除すると、下のエラーも出なくなりました。

~~残念ながら、このエラーを取り除いても、書き出しの時に、~~

```python
ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters
```

~~って怒られるので、もうちょっと改良が必要な場合があるのでご注意。~~
~~データクリーニングしてから実験しましょうというお話。~~

# 後記
初投稿なので、問題等あれば、バシバシ指摘してください。
では。