Pandas.ExcelWriter로 Excel 열 너비를 자동 조정하는 방법이 있습니까?


104

일부 Excel 보고서를 생성하라는 요청을 받았습니다. 현재 데이터에 pandas를 상당히 많이 사용하고 있으므로 당연히 pandas.ExcelWriter 메서드를 사용하여 이러한 보고서를 생성하고 싶습니다. 그러나 고정 된 열 너비가 문제입니다.

지금까지 가지고있는 코드는 충분히 간단합니다. 'df'라는 데이터 프레임이 있다고 가정합니다.

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

팬더 코드를 살펴 보았는데 열 너비를 설정하는 옵션이 실제로 보이지 않습니다. 열이 데이터에 맞게 자동 조정되도록 만드는 트릭이 유니버스에 있습니까? 아니면 xlsx 파일에서 열 너비를 조정하기 위해 할 수있는 일이 있습니까?

(저는 OpenPyXL 라이브러리를 사용하고 있으며 .xlsx 파일을 생성하고 있습니다-차이가 있다면.)

감사합니다.


1
지금은 가능하지 않은 것 같습니다. github에서이 개선 사항에 대한 문제를여십시오 (아마도 PR?). 그렇게 어렵게 보이지 않습니다.
Jeff

감사합니다 Jeff, 나는 문제를 제출했습니다. 나는 확실히 팬더 그것을 해결하기 위해 코드베이스에 실제로 다이빙에 시간이한다면 모르겠지만, 당신은 : 절대 모릅니다
badideas

네 .... 당신의 문제를 보았습니다 ..... 도움이 필요하면 문제에 대한 의견을 남겨주세요! (본질적으로 선택적 인수를에 전달해야합니다. 여기에는 to_excel아마도 col_style=dictcol 헤더 스타일 요소 header_style가 포함될 수 있습니다 (현재 하드 코딩 된 것처럼 보이는 기본값 이
Jeff

답변:


59

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()

8
참고 : 제 경우에는 "df.to_excel (...)"호출에서 "index = False"를 사용해야했습니다. 그렇지 않으면 열이 1까지 꺼졌습니다
denvar

1
그래, 나는 또한 df.to_excel를 추가했다 (작가, 시트 _ = 시트 이름, 지수는 거짓 =)
헤이 키 Pulkkinen

2
index = False를 사용할 수없는 경우 (행에 다중 인덱스가 있기 때문에) df.index.nlevels로 인덱스 수준 깊이를 얻은 다음이를 사용하여 설정된 열 호출에 추가 할 수 worksheet.set_column(idx+nlevels, idx+nlevels, max_len)있습니다.. 그렇지 않으면 프레임의 첫 번째 열에 대해 길이가 계산 된 다음 Excel의 첫 번째 열 (인덱스 일 가능성이 있음)에 적용 됩니다.
ac24

1
이 대답을 찾는 사람 은 .NET의 각 열을 반복하고 있기 때문에 enumerate(df)이어야합니다 . enumerate(df.columns)df
Dascienz

2
이상 같은 방식으로 반복하는 @Dascienz dict실제로는의 키 반복 할 dict(수동 말을하지 않는 dict.keys()이상 반복) pd.DataFrame열을 반복합니다. 수동으로 반복 할 필요가 없습니다 df.columns.
alichaudry

28

방금 동일한 문제가 발생하여 Xlsxwriter 및 pandas에 대한 공식 문서에이 기능이 아직 지원되지 않는 것으로 나열되어 있음을 발견했기 때문에 이것을 게시하고 있습니다. 나는 내가 가진 문제를 해결하는 솔루션을 함께 해킹했습니다. 기본적으로 각 열을 반복하고 workstation.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()

1
좋은 솔루션입니다. 다른 패키지 대신 판다를 사용한 방식이 마음에 듭니다.

()max 함수 안에 필요하다고 생각합니다 :`max (column_len (), len (col)) + 2`
Serdia

21

지금 당장 자동으로 수행하는 방법은 없지만 openpyxl을 사용하면 다음 줄 ( 수동으로 수행하는 방법대한 사용자 Bufke의 다른 답변에서 수정 됨 )을 사용하여 정상적인 값 (문자 너비)을 지정할 수 있습니다.

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

pandas가 사용하는 기본 ExcelWriter 엔진은 2013 년부터 column_dimensions특성을 포함하지 않는 Xlsxwriter로 변경되었습니다 . openpyxl을 계속 사용하려면 다음을 사용하여 작성기를 작성할 때 지정하십시오.pd.ExcelWriter(excel_filename, engine='openpyxl')
ojdo

@Sunil : Xlsxwriter오늘의 기본 엔진으로 열 너비를 지정하는 방법을 보려면 엔진으로 사용하는 다른 답변 을 확인하십시오.
ojdo

21

최근에 사용하기 시작한 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

버전 1.4에서 best_fit인수가 StyleFrame.to_excel. 설명서를 참조하십시오 .

업데이트 2

다음은 StyleFrame 3.xx에서 작동하는 코드 샘플입니다.

from styleframe import StyleFrame
import pandas as pd

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

StyleFrame 패키지는 사용하기 쉽지만 "기본적으로 열 너비가 자동 조정"되는 방식을 알지 못합니다. 제공 한 코드 샘플을 실행하면 모든 열의 너비가 같고 세 개의 헤더가 모두 래핑됩니다. 샘플 데이터는 자연스럽게 너비가 거의 동일하기 때문에 제대로 선택되지 않습니다. 자동 조정을 실제로 설명하려면 매우 넓은 데이터와 좁은 데이터를 선택해야합니다. 이 작업을 직접 수행하면 열 너비가 여전히 이전과 동일합니다. 전혀 조정이 없었습니다.
John Y

StyleFrame의 히스토리 중 한 지점에서 기본적으로 열 너비가 자동으로 조정되었지만 적어도 오늘은 best_fit매개 변수 에서 조정하려는 열을 지정해야합니다 . 또한 이것을 시도했을 때 매우 좋지 않은 결과를 얻었습니다 .
John Y

너비가 한 열에서 벗어난 것 같습니다. index매개 변수를 활성화 및 비활성화하려고 시도 했지만 주사위는 없습니다.

1
감사! 예를 들어 헤더에 더 많은 스타일을 추가하는 방법 : sf.apply_headers_style(Styler(bold=False))그것을 알아내는 데 오랜 시간이 걸렸습니다. 그리고 import 문에서 from StyleFrame import StyleFrame, Styler. 다음은 굵게 표시되지 않은 모든 옵션입니다. styleframe.readthedocs.io/en/2.0.5/…
Nikhil VJ

1
@Hagbard 버전 3부터 가져 오기는 from styleframe import StyleFramePEP8 이름 규칙을 준수하기 위해 이루어져야합니다
DeepSpace

11

pandas와 xlsxwriter를 사용하면 작업을 수행 할 수 있습니다. 아래 코드는 Python 3.x에서 완벽하게 작동합니다. pandas로 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()

5

모든 열 길이를 동적으로 조정

writer = pd.ExcelWriter('/path/to/output/file.xlsx') 
df.to_excel(writer, sheet_name='sheetName', index=False, na_rep='NaN')

for column in df:
    column_length = max(df[column].astype(str).map(len).max(), len(column))
    col_idx = df.columns.get_loc(column)
    writer.sheets['sheetName'].set_column(col_idx, col_idx, column_length)

열 이름을 사용하여 수동으로 열 조정

col_idx = df.columns.get_loc('columnName')
writer.sheets['sheetName'].set_column(col_idx, col_idx, 15)

열 인덱스를 사용하여 수동으로 열 조정

writer.sheets['sheetName'].set_column(col_idx, col_idx, 15)

위 중 하나라도 실패한 경우

AttributeError: 'Worksheet' object has no attribute 'set_column'

다음을 설치하십시오 xlsxwriter.

pip install xlsxwriter

4

열 내용보다는 열 머리글을 기준으로 열을 조정하는 것이 더 유용하다는 것을 알았습니다.

사용 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

4

직장에서 저는 항상 파일을 엑셀하기 위해 데이터 프레임을 작성하고 있습니다. 따라서 동일한 코드를 반복해서 작성하는 대신 모듈러스를 만들었습니다. 이제 가져 와서 Excel 파일을 작성하고 형식화하는 데 사용합니다. 하지만 한 가지 단점이 있지만 데이터 프레임이 너무 크면 시간이 오래 걸립니다. 그래서 여기에 코드가 있습니다 :

def result_to_excel(output_name, dataframes_list, sheet_names_list, output_dir):
    out_path = os.path.join(output_dir, output_name)
    writerReport = pd.ExcelWriter(out_path, engine='xlsxwriter',
                    datetime_format='yyyymmdd', date_format='yyyymmdd')
    workbook = writerReport.book
    # loop through the list of dataframes to save every dataframe into a new sheet in the excel file
    for i, dataframe in enumerate(dataframes_list):
        sheet_name = sheet_names_list[i]  # choose the sheet name from sheet_names_list
        dataframe.to_excel(writerReport, sheet_name=sheet_name, index=False, startrow=0)
        # Add a header format.
        format = workbook.add_format({
            'bold': True,
            'border': 1,
            'fg_color': '#0000FF',
            'font_color': 'white'})
        # Write the column headers with the defined format.
        worksheet = writerReport.sheets[sheet_name]
        for col_num, col_name in enumerate(dataframe.columns.values):
            worksheet.write(0, col_num, col_name, format)
        worksheet.autofilter(0, 0, 0, len(dataframe.columns) - 1)
        worksheet.freeze_panes(1, 0)
        # loop through the columns in the dataframe to get the width of the column
        for j, col in enumerate(dataframe.columns):
            max_width = max([len(str(s)) for s in dataframe[col].values] + [len(col) + 2])
            # define a max width to not get to wide column
            if max_width > 50:
                max_width = 50
            worksheet.set_column(j, j, max_width)
    writerReport.save()
    return output_dir + output_name


이 코드를 복제 할 때 다음 오류가 발생했습니다. AttributeError : 'str'object has no attribute 'to_excel'. "dataframe_list"가 생성되는 방식과 관련이 있다고 생각합니다. Mine은 6 개의 데이터 프레임 이름이있는 목록입니다
user3019973

예, "dataframe_list"에는 데이터 프레임 이름이 아닌 데이터 프레임이 있어야합니다.
rafat.ch

2

다른 답변과 댓글을 결합하고 다중 인덱스도 지원합니다.

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()

2
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

1

가장 쉬운 해결책은 set_column 메서드에서 열 너비를 지정하는 것입니다.

    for worksheet in writer.sheets.values():
        worksheet.set_column(0,last_column_value, required_width_constant)

1
def auto_width_columns(df, sheetname):
    workbook = writer.book  
    worksheet= writer.sheets[sheetname] 

    for i, col in enumerate(df.columns):
        column_len = max(df[col].astype(str).str.len().max(), len(col) + 2)
        worksheet.set_column(i, i, column_len)

1
코드는 몇 가지 설명을 추가하거나 시간을 들여 좋은 답변을 작성하는 방법
Gad

1
여보세요! 이 코드가 문제를 해결할 수 있지만 문제를 해결하는 방법과 이유에 대한 설명포함 하여 게시물의 품질을 향상시키는 데 실제로 도움이되며 더 많은 찬성 투표가 발생할 수 있습니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오. 제발 편집 설명을 추가하고 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Brian

0

예, xlsx 파일에서 열 너비를 조정하기 위해 수행 할 수있는 작업이 있습니다. xlwings를 사용하여 열 을 자동 맞춤 합니다. 매우 간단한 솔루션입니다. 예제 코드의 마지막 여섯 줄을 참조하십시오. 이 절차의 장점은 글꼴 크기, 글꼴 유형 또는 다른 것에 대해 걱정할 필요가 없다는 것입니다. 요구 사항 : Excel 설치.

import pandas as pd
import xlwings as xw

report_file = "test.xlsx"

df1 = pd.DataFrame([
    ('this is a long term1', 1, 1, 3),
    ('this is a long term2', 1, 2, 5),
    ('this is a long term3', 1, 1, 6),
    ('this is a long term2', 1, 1, 9),
    ], columns=['term', 'aaaa', 'bbbbbbb', "cccccccccccccccccccccccccccccccccccccccccccccc"])

writer = pd.ExcelWriter(report_file, engine="xlsxwriter")
df1.to_excel(writer, sheet_name="Sheet1", index=False)

workbook = writer.book
worksheet1 = writer.sheets["Sheet1"]
num_format = workbook.add_format({"num_format": '#,##0.00'})

worksheet1.set_column("B:D", cell_format=num_format)
writer.save()

# Autofit all columns with xlwings.
app = xw.App(visible=False)
wb = xw.Book(report_file)

for ws in wb.sheets:
    ws.autofit(axis="columns")

wb.save(report_file)
app.quit()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.