Библиотека xslxwriter в Python неожиданно очень медленно - PullRequest
2 голосов
/ 31 октября 2019

Я использую библиотеку xlsxwriter для форматирования и записи кадров данных pandas, чтобы преуспеть. Библиотека необходима из-за необходимого мне различного форматирования (заголовки, таблица и т. Д., Поэтому я не использую df.to_excel ()). Я перебираю строки и столбцы кадра данных, чтобы написать электронную таблицу.

Это работало нормально для многих применений за последний год, включая большие кадры данных (> 100 000 строк, 13 столбцов). Однако, это внезапно стало чрезвычайно медленным. Это все еще работает, но теперь то, что раньше занимало несколько минут или около того, чтобы написать (что, кажется, соответствует документации xlsxwriter в https://xlsxwriter.readthedocs.io/working_with_memory.html), теперь записывается вечно (100 строк занимает 40 секунд, поэтому 100 000+ строк занимаетнавсегда). Я не знаю, в чем отличие, поскольку сам код такой же и все еще работает, только медленно. Я перезагрузил свой компьютер и обновил все свои библиотеки, включая xlsxwriter. Мой другой код, который не использует xlsxwriter, кажется, всебудет работать с нормальной скоростью, так что, похоже, это специфично для xlsxwriter. Я использую дистрибутив Python Anaconda.

Есть ли какая-либо причина, по которой одна библиотека, такая как xlswriter, внезапно начнет работать медленно? Я делаю это нарабочий компьютер, так что, может быть, они что-то изменили? Я знаю, что они планируют обновить версии Excel, но еще не сделали этого. Я просто не могу понять это.

К вашему сведению, мой код (который ранее выполнялся по разумнойСкорость) ниже.

Обратите внимание, что если бы было возможно записать pandas dataframe to Excel, а затем отформатировать его в виде таблицы с отформатированными строками заголовков, тогда я пропущу цикл, но я не думаю, что это так.

 # Populate data.
        exceptions = exceptions.fillna('')  # NA values not supported.
        row = 3
        i = 0
        while row < len(exceptions) + 3:
            n = 0
            while n < len(column_formats):
                col_name = column_formats[n][0]
                col_format = column_formats[n][2]
                if col_format == 'string':
                    exceptions[col_name].iloc[i] = str(exceptions[col_name].iloc[i])
                    worksheet.write_string(row, n, exceptions[col_name].iloc[i])
                elif col_format == 'number':
                    if type(exceptions[col_name].iloc[i]) in [int, float, np.int32, np.float32, np.int64, np.float64]:
                        worksheet.write_number(row, n, exceptions[col_name].iloc[i],
                                               number_format)
                    else:
                        worksheet.write_string(row, n, exceptions[col_name].iloc[i])
                elif col_format == 'dollar':
                    if type(exceptions[col_name].iloc[i]) in [int, float, np.int32, np.float32, np.int64, np.float64]:
                        worksheet.write_number(row, n, exceptions[col_name].iloc[i],
                                               dollar_format)
                    else:
                        worksheet.write_string(row, n, exceptions[col_name].iloc[i])
                elif col_format == 'datetime':
                    # If date, then convert to python datetime and write to Excel.
                    if type(exceptions[col_name].iloc[i]) == pd.Timestamp:
                        date = exceptions[col_name].iloc[i].to_pydatetime()
                        worksheet.write_datetime(row, n, date,
                                                 date_format)
                    else:
                        worksheet.write_string(row, n, exceptions[col_name].iloc[i])
                elif col_format == 'boolean':
                    if type(exceptions[col_name].iloc[i]) == bool:
                        worksheet.write_boolean(row, n, exceptions[col_name].iloc[i])
                    else:
                        worksheet.write_string(row, n, exceptions[col_name].iloc[i])
                n +=1
            row += 1
            i += 1

1 Ответ

0 голосов
/ 31 октября 2019

Хорошо, я не уверен, почему цикл начал занимать так много времени, но я нашел способ записать это в кадр данных pandas, а затем добавить заголовок, отформатировать его и затем превратить в таблицу. Для 140 тыс. Строк и 13 столбцов требуется чуть меньше минуты.

Подробнее см. https://xlsxwriter.readthedocs.io/pandas_examples.html.

Ниже показано, как я превратил блок данных в таблицу на случай, если кому-то будет интересно:

        if len(column_formats) + ex_cols <= 27:
            col_string = string.ascii_uppercase[len(column_formats) + ex_cols]
        else:
            col_string = 'A' + string.ascii_uppercase[len(column_formats) + ex_cols - 27]

        table_range = ('A3:' + col_string + str(len(exceptions) + 3))
        col_headers = self._create_col_headers(column_formats, override_header)
        worksheet.add_table(table_range, {'style': 'Table Style Medium 4',
                                          'columns': col_headers})

def _create_col_headers(self, column_formats, override_header=None):
        ''''Creates a list of dictionaries of column headers, used to add table
        format in Excel formatting'''
        i = 0
        col_headers = []
        while i < len(column_formats):
            col_name = column_formats[i][0]
            col_headers.append({'header': col_name})
            i += 1

        # Add column for Review Notes (at end) (if no override).
        if override_header is None:
            col_headers.append({'header': 'Review Notes'})

        return col_headers
...