Есть ли способ автоматической настройки ширины столбцов Excel с помощью pandas.ExcelWriter?
Мне предлагается создать несколько отчетов Excel. В настоящее время я использую pandas довольно сильно для своих данных, поэтому, естественно, я хотел бы использовать метод pandas.ExcelWriter для генерации этих отчетов. Однако фиксированные ширины столбцов являются проблемой.
Код, который я до сих пор достаточно прост. Скажем, у меня есть dataframe, называемый 'df':
writer = pd.ExcelWriter(excel_file_path)
df.to_excel(writer, sheet_name="Summary")
Я просматривал код pandas, и я не вижу никаких параметров для установки ширины столбцов. Есть ли трюк в юниверсе, чтобы сделать его таким, чтобы столбцы автоматически настраивались на данные? Или я могу что-то сделать после факта в файл xlsx, чтобы настроить ширину столбцов?
(Я использую библиотеку OpenPyXL и генерирую файлы .xlsx - если это имеет значение.)
Спасибо.
Ответы
Ответ 1
Вдохновленный 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()
Ответ 2
Вероятно, нет автоматического способа сделать это прямо сейчас, но поскольку вы используете openpyxl, следующая строка (адаптирована из другого ответа пользователя Bufke на как это сделать вручную) позволяет вам указывать нормальное значение (в ширине символов):
writer.sheets['Summary'].column_dimensions['A'].width = 15
Ответ 3
Я публикую это, потому что столкнулся с той же проблемой и обнаружил, что в официальной документации для Xlsxwriter и pandas эта функция по-прежнему указана как неподдерживаемая. Я взломал решение, которое решило проблему, с которой я столкнулся. Я просто перебираю каждый столбец и использую worksheet.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']
#Iterate through each column and set the width == the max length in that column. A padding length of 2 is also added.
for i, col in enumerate(my_dataframe.columns):
# find length of column i
column_len = my_dataframe[col].astype(str).str.len().max()
# Setting the length if the column header is larger
# than the max column value length
column_len = max(column_len, len(col)) + 2
# set the column length
worksheet.set_column(i, i, column_len)
writer.save()
Ответ 4
Есть хороший пакет, который я начал использовать недавно, называется 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)
ОБНОВИТЬ
В версии 1.4 аргумент best_fit
был добавлен в StyleFrame.to_excel
. Смотрите документацию.
Ответ 5
Используя pandas и xlsxwriter, вы можете выполнить свою задачу, приведенный ниже код будет отлично работать в Python 3.x. Для получения дополнительной информации о работе с XlsxWriter с пандами эта ссылка может быть полезна https://xlsxwriter.readthedocs.io/working_with_pandas.html
import pandas as pd
writer = pd.ExcelWriter(excel_file_path, engine='xlsxwriter')
df.to_excel(writer, sheet_name="Summary")
workbook = writer.book
worksheet = writer.sheets["Summary"]
#set the column width as per your requirement
worksheet.set_column('A:A', 25)
writer.save()
Ответ 6
import re
import openpyxl
..
for col in _ws.columns:
max_lenght = 0
print(col[0])
col_name = re.findall('\w\d', str(col[0]))
col_name = col_name[0]
col_name = re.findall('\w', str(col_name))[0]
print(col_name)
for cell in col:
try:
if len(str(cell.value)) > max_lenght:
max_lenght = len(cell.value)
except:
pass
adjusted_width = (max_lenght+2)
_ws.column_dimensions[col_name].width = adjusted_width
Ответ 7
Я обнаружил, что было бы более полезно настроить столбец на основе заголовка столбца, а не содержимого столбца.
Используя df.columns.values.tolist()
, я генерирую список заголовков столбцов и использую длины этих заголовков, чтобы определить ширину столбцов.
Смотрите полный код ниже:
import pandas as pd
import xlsxwriter
writer = pd.ExcelWriter(filename, engine='xlsxwriter')
df.to_excel(writer, index=False, sheet_name=sheetname)
workbook = writer.book # Access the workbook
worksheet= writer.sheets[sheetname] # Access the Worksheet
header_list = df.columns.values.tolist() # Generate list of headers
for i in range(0, len(header_list)):
worksheet.set_column(i, i, len(header_list[i])) # Set column widths based on len(header)
writer.save() # Save the excel file
Ответ 8
Самое простое решение - указать ширину столбца в методе set_column.
for worksheet in writer.sheets.values():
worksheet.set_column(0,last_column_value, required_width_constant)
Ответ 9
Объединение других ответов и комментариев, а также поддержка мультииндексов:
def autosize_excel_columns(worksheet, df):
autosize_excel_columns_df(worksheet, df.index.to_frame())
autosize_excel_columns_df(worksheet, df, offset=df.index.nlevels)
def autosize_excel_columns_df(worksheet, df, offset=0):
for idx, col in enumerate(df):
series = df[col]
max_len = max((
series.astype(str).map(len).max(),
len(str(series.name))
)) + 1
worksheet.set_column(idx+offset, idx+offset, max_len)
sheetname=...
df.to_excel(writer, sheet_name=sheetname, freeze_panes=(df.columns.nlevels, df.index.nlevels))
worksheet = writer.sheets[sheetname]
autosize_excel_columns(worksheet, df)
writer.save()