Есть ли способ автоматически настроить ширину столбцов Excel с помощью pandas.ExcelWriter?

23

Мне предлагается создать несколько отчетов Excel. В настоящее время я использую pandas довольно сильно для своих данных, поэтому, естественно, я хотел бы использовать метод pandas.ExcelWriter для генерации этих отчетов. Однако фиксированные ширины столбцов являются проблемой.

Код, который я до сих пор достаточно прост. Скажем, у меня есть dataframe, называемый 'df':

writer = pd.ExcelWriter(excel_file_path)
df.to_excel(writer, sheet_name="Summary")

Я просматривал код pandas, и я не вижу никаких параметров для установки ширины столбцов. Есть ли трюк в юниверсе, чтобы сделать его таким, чтобы столбцы автоматически настраивались на данные? Или я могу что-то сделать после факта в файл xlsx, чтобы настроить ширину столбцов?

(Я использую библиотеку OpenPyXL и генерирую файлы .xlsx - если это имеет значение.)

Спасибо.

  • 1
    на данный момент не представляется возможным, пожалуйста, откройте вопрос для этого улучшения на GitHub (и, возможно, PR?). не выглядит так сложно сделать.
  • 0
    спасибо Джефф, я представил вопрос. я не уверен, что у меня будет время, чтобы действительно погрузиться в кодовую базу панд, чтобы решить ее, но вы никогда не знаете :)
Показать ещё 2 комментария
Теги:
pandas
excel
openpyxl

4 ответа

13

Вероятно, нет автоматического способа сделать это прямо сейчас, но поскольку вы используете openpyxl, следующая строка (адаптирована из другого ответа пользователя Bufke на как это сделать вручную) позволяет вам указывать нормальное значение (в ширине символов):

writer.sheets['Summary'].column_dimensions['A'].width = 15
7

Вдохновленный user6178746 ответом выше, у меня есть следующее:

# Given a dict of dataframes, for example:
# dfs = {'gadgets': df_gadgets, 'widgets': df_widgets}

writer = pd.ExcelWriter(filename, engine='xlsxwriter')
for sheetname, df in dfs.items():  # loop through `dict` of dataframes
    df.to_excel(writer, sheet_name=sheetname)  # send df to writer
    worksheet = writer.sheets[sheetname]  # pull worksheet object
    for idx, col in enumerate(df):  # loop through all columns
        series = df[col]
        max_len = max((
            series.astype(str).map(len).max(),  # len of largest item
            len(str(series.name))  # len of column name/header
            )) + 1  # adding a little extra space
        worksheet.set_column(idx, idx, max_len)  # set column width
writer.save()
  • 3
    К вашему сведению: в моем случае мне нужно было использовать «index = False» в вызове «df.to_excel (...)», иначе столбцы были отключены на 1
  • 0
    да, я также должен был добавить df.to_excel (писатель, имя_сталицы = имя_станицы, индекс = False)
Показать ещё 5 комментариев
5

Есть хороший пакет, который я начал использовать недавно, называемый StyleFrame.

он получает DataFrame и позволяет вам легко стилизовать его...

по умолчанию ширина колонок автоматически настраивается.

например:

from StyleFrame import StyleFrame
import pandas as pd

df = pd.DataFrame({'aaaaaaaaaaa': [1, 2, 3], 'bbbbbbbbb': [1, 1, 1], 'ccccccccccc': [2, 3, 4]})
excel_writer = StyleFrame.ExcelWriter('example.xlsx')
sf = StyleFrame(df)
sf.to_excel(excel_writer=excel_writer, row_to_add_filters=0, columns_and_rows_to_freeze='B2')
excel_writer.save()

вы также можете изменить ширину столбцов:

sf.set_column_width(columns=['aaaaaaaaaaa', 'bbbbbbbbb'], width=35.3)
  • 0
    Пакет StyleFrame может быть простым в использовании, но я не вижу, как «по умолчанию ширина столбцов настраивается автоматически». Когда я запускаю приведенный вами пример кода, все столбцы имеют одинаковую ширину, а все три заголовка переносятся. Ваши выборочные данные также плохо выбраны, потому что все они, естественно, имеют почти одинаковую ширину. Чтобы действительно проиллюстрировать автоматическую настройку, вы должны выбрать действительно широкие и узкие данные. Когда я делаю это для себя, ширина столбцов остается точно такой же, как и раньше. Там не было никакой корректировки вообще.
  • 0
    Может быть, в какой-то момент в истории StyleFrame ширина столбцов автоматически настраивалась по умолчанию, но, по крайней мере, сегодня вы должны указать столбец или столбцы, которые хотите настроить, в параметре best_fit . Кроме того, когда я попробовал это, я получил очень плохие результаты .
Показать ещё 1 комментарий
4

Я публикую это, потому что я просто столкнулся с той же проблемой и обнаружил, что официальная документация для Xlsxwriter и pandas по-прежнему содержит перечисленные функции как неподдерживаемые. Я взломал решение, которое решило проблему, с которой я столкнулся. Я в основном просто перебираю каждый столбец и использую workheet.set_column, чтобы установить ширину столбца == максимальную длину содержимого этого столбца.

Одно важное замечание. Это решение не соответствует заголовкам столбцов, просто значения столбца. Это должно быть легким изменением, но если вам нужно подгонять заголовки. Надеюсь, это поможет кому-то:)

import pandas as pd
import sqlalchemy as sa
import urllib


read_server = 'serverName'
read_database = 'databaseName'

read_params = urllib.quote_plus("DRIVER={SQL Server};SERVER="+read_server+";DATABASE="+read_database+";TRUSTED_CONNECTION=Yes")
read_engine = sa.create_engine("mssql+pyodbc:///?odbc_connect=%s" % read_params)

#Output some SQL Server data into a dataframe
my_sql_query = """ SELECT * FROM dbo.my_table """
my_dataframe = pd.read_sql_query(my_sql_query,con=read_engine)

#Set destination directory to save excel.
xlsFilepath = r'H:\my_project' + "\\" + 'my_file_name.xlsx'
writer = pd.ExcelWriter(xlsFilepath, engine='xlsxwriter')

#Write excel to file using pandas to_excel
my_dataframe.to_excel(writer, startrow = 1, sheet_name='Sheet1', index=False)

#Indicate workbook and worksheet for formatting
workbook = writer.book
worksheet = writer.sheets['Sheet1']

#Find the number of columns to iterate through
columns = len(my_dataframe.columns)
column_series = pd.Series(range(columns))
column_list = column_series.tolist()

#Iterate through each column and set the width == the max length in that column.
for i in column_list:
    #find length of column i
    column_len = my_dataframe[[i]].astype(str).apply(lambda x: x.str.len()).max().max()
    #set the column length
    worksheet.set_column(i,i,column_len)
writer.save()

ИЗМЕНИТЬ

Ниже приведено обновление, в котором рассматривается проблема столбца. Если заголовок столбца больше длины максимального столбца, чем используется заголовок столбца. Я также добавил буфер из 2, чтобы дать небольшое дополнение.

#Iterate through each column and set the width == the max length in that column.
for i in column_list:
    #filter for header
    header = my_dataframe[[i]].astype(str).columns.values
    #Get length of header    
    header_len = len(header.max()) + 2
    #Get length of column values
    column_len = my_dataframe[[i]].astype(str).apply(lambda x: x.str.len()).max().max() + 2
    #Choose the greater of the column length or column value length
    if header_len >= column_len:
        worksheet.set_column(i,i,header_len)
    else:
        worksheet.set_column(i,i,column_len)   
writer.save()
  • 1
    Хорошее решение Мне нравится, как вы использовали панд вместо другой упаковки.
  • 0
    Эта ссылка также может быть полезна: xlsxwriter.readthedocs.io/worksheet.html

Ещё вопросы

Сообщество Overcoder
Наверх
Меню