【问题标题】:How to remove illegal characters so a dataframe can write to Excel如何删除非法字符以便数据框可以写入 Excel
【发布时间】:2017-02-17 20:24:32
【问题描述】:

我正在尝试使用 ExcelWriter 将数据框写入 Excel 电子表格,但它一直返回错误:

openpyxl.utils.exceptions.IllegalCharacterError

我猜 ExcelWriter 不喜欢数据框中的某些字符。看起来很奇怪,因为数据框是由三个 Excel 电子表格组成的,所以我看不出 Excel 不喜欢的字符!

有没有办法遍历数据框并替换 ExcelWriter 不喜欢的字符?我什至不介意它是否只是删除它们。

从数据框中删除或替换非法字符的最佳方法是什么?

【问题讨论】:

标签: pandas export-to-excel


【解决方案1】:

根据苏海鹏的回答,我添加了一个功能:

dataframe = dataframe.applymap(lambda x: x.encode('unicode_escape').
                 decode('utf-8') if isinstance(x, str) else x)

基本上,如果存在 unicode 字符,它会对其进行转义。它成功了,我现在可以再次写入 Excel 电子表格了!

【讨论】:

  • 好吧....它可以工作,但生成的文件内容类似于“\u4ee5\u4e0b\u6587\u9577...”
【解决方案2】:

同样的问题也发生在我身上。我解决了如下:

  1. 安装python包xlsxwriter:
pip install xlsxwriter
  1. 将默认引擎“openpyxl”替换为“xlsxwriter”:
dataframe.to_excel("file.xlsx", engine='xlsxwriter')

【讨论】:

    【解决方案3】:

    尝试使用不同的 excel 编写器引擎解决了我的问题。

    writer = pd.ExcelWriter('file.xlsx', engine='xlsxwriter')
    

    【讨论】:

    • 有人在我的一个报告中返回的一个字段中写了“ES côté病”,Python 对此感到窒息。我进行了建议的更改,并且效果很好。
    • 这很好,但是你如何使用这个引擎而不覆盖当前文件?
    • FFR,如果您收到No module named 'xlsxwriter' 错误,您可能需要运行pip install xlsxwriter,因为xlsxwriter 似乎是pandas 的可选依赖项(意味着它不会被预安装)
    【解决方案4】:

    如果您不想安装另一个 Excel 编写器引擎(例如 xlsxwriter),您可以尝试通过查找导致出现 IllegalCharacterError 错误的模式来删除这些非法字符。

    打开位于/path/to/your/python/site-packages/openpyxl/cell/cell.py,查找check_string 函数,您会看到它使用定义的正则表达式模式ILLEGAL_CHARACTERS_RE 来查找那些非法字符。试图找到它的定义,你会看到这一行:

    ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')

    这一行是您删除这些字符所需要的。将此行复制到您的程序并在将数据框写入 Excel 之前执行以下代码:

    dataframe = dataframe.applymap(lambda x: ILLEGAL_CHARACTERS_RE.sub(r'', x) if isinstance(x, str) else x)

    以上行将删除每个单元格中的这些字符。


    但是这些字符的来源可能是个问题。正如您所说,数据框来自三个 Excel 电子表格。如果源 Excel 电子表格包含这些字符,您仍将面临此问题。因此,如果您可以控制源电子表格的生成过程,请尝试从那里删除这些字符。

    【讨论】:

    • 哇,唯一真正起作用的东西,我过去 3 天一直在研究这个问题。非常感谢!
    • 如何将任何ILLEGAL_CHARACTERS 替换为特定字符串?
    • @Rami Alloush dataframe = dataframe.applymap(lambda x: ILLEGAL_CHARACTERS_RE.sub(STRING_YOU_WANT, x) if isinstance(x, str) else x) 更改 STRING_YOU_WANT
    • 不错的解决方案。而不是重新定义ILLEGAL_CHARACTERS_RE,你可以像from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE一样从openpyxl导入它。
    【解决方案5】:

    在将数据框写入 html 或 csv 时,我还在为数据框中的一些奇怪字符而苦苦挣扎。例如,对于带重音的字符,我无法写入 html 文件,因此我需要将字符转换为不带重音的字符。

    我的方法可能不是最好的,但它可以帮助我将unicode 字符串转换为ascii 兼容。

    # install unidecode first 
    from unidecode import unidecode
    
    def FormatString(s):
    if isinstance(s, unicode):
      try:
        s.encode('ascii')
        return s
      except:
        return unidecode(s)
    else:
      return s
    
    df2 = df1.applymap(FormatString) 
    

    在您的情况下,如果您只是想通过将return unidecode(s) 更改为return 'StringYouWantToReplace' 来摆脱非法字符。

    希望这能给我一些想法来解决您的问题。

    【讨论】:

    • 谢谢!那真的很有帮助。根据您的建议,我使用了类似的东西。
    【解决方案6】:

    您可以对 python 字符串使用内置的strip() 方法。

    对于每个单元格:

    text = str(illegal_text).strip()
    
    

    对于整个数据框:

    dataframe = dataframe.applymap(lambda t: str(t).strip())
    

    【讨论】:

      【解决方案7】:

      如果您仍在努力清理字符,这对我来说效果很好:

      import xlwings as xw
      import pandas as pd
      df = pd.read_pickle('C:\\Users\\User1\\picked_DataFrame_notWriting.df')
      topath = 'C:\\Users\\User1\\tryAgain.xlsx'
      wb = xw.Book(topath)
      ws = wb.sheets['Data']
      ws.range('A1').options(index=False).value = df
      wb.save()
      wb.close()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-20
        • 1970-01-01
        • 2020-04-30
        • 2013-09-08
        • 2014-10-05
        • 2010-11-04
        • 1970-01-01
        相关资源
        最近更新 更多