क्या pandas.ExcelWriter के साथ एक्सेल कॉलम की चौड़ाई को ऑटो-एडजस्ट करने का कोई तरीका है?


104

मुझे कुछ एक्सेल रिपोर्ट बनाने के लिए कहा जा रहा है। मैं वर्तमान में अपने डेटा के लिए पंडों का बहुत अधिक उपयोग कर रहा हूं, इसलिए स्वाभाविक रूप से मैं इन रिपोर्टों को उत्पन्न करने के लिए पंडों का उपयोग करना चाहूंगा। एक्सट्रलर विधि। हालाँकि निश्चित कॉलम चौड़ाई एक समस्या है।

मेरे पास अब तक का कोड काफी सरल है। कहो कि मेरे पास 'df' नामक एक डेटाफ्रेम है:

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

मैं पांडा कोड देख रहा था, और मैं वास्तव में कॉलम की चौड़ाई निर्धारित करने के लिए कोई विकल्प नहीं देखता हूं। क्या ब्रह्माण्ड में कोई चाल है जो इसे इस तरह बनाती है कि कॉलम डेटा में ऑटो-एडजस्ट हो जाए? या स्तंभ चौड़ाई को समायोजित करने के लिए xlsx फ़ाइल के तथ्य के बाद क्या मैं कुछ कर सकता हूं?

(मैं OpenPyXL लाइब्रेरी का उपयोग कर रहा हूं, और .xlsx फाइलें पैदा कर रहा हूं - अगर इससे कोई फर्क पड़ता है।)

धन्यवाद।


1
फिलहाल संभव नहीं दिखता है, कृपया जीथब (और शायद पीआर?) पर इस वृद्धि के लिए एक मुद्दा खोलें। ऐसा करना मुश्किल नहीं दिखता।
जेफ

धन्यवाद जेफ, मैंने मुद्दा प्रस्तुत किया है। मुझे यकीन नहीं है कि अगर मेरे पास इसे हल करने के लिए वास्तव में पांडा कोडबेस में गोता लगाने का समय होगा, लेकिन आप कभी नहीं जानते :)
badideas

हाँ .... अपने मुद्दे को देखा ..... अगर आपको कुछ मदद चाहिए तो मुद्दे पर टिप्पणी करें! (अनिवार्य रूप से करने के लिए एक वैकल्पिक तर्क पारित करने की आवश्यकता है to_excel, हो सकता है col_style=dictजिसमें कोल हेडर स्टाइल एलिमेंट्स हों (बजाय डिफ़ॉल्ट के header_styleजो अब हार्ड कोडित लगता है
जेफ

जवाबों:


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
FYI करें: मेरे मामले में मुझे "df.to_excel (...)" कॉल में "index = False" का उपयोग करने की आवश्यकता थी, अन्यथा कॉलम 1 से बंद थे
denvar

1
हां, मुझे df.to_excel (लेखक, sheet_name = sheetname, index = False) भी जोड़ना था
Heikki Pulkkinen

2
यदि आप अनुक्रमणिका = गलत का उपयोग नहीं कर सकते हैं (क्योंकि आपके पास पंक्तियों पर एक बहु बिंदु है), तो आप df.index.nlevels के साथ सूचकांक स्तर की गहराई प्राप्त कर सकते हैं और फिर अपने सेट कॉलम कॉल में जोड़ने के लिए इसका उपयोग कर सकते हैं worksheet.set_column(idx+nlevels, idx+nlevels, max_len):। अन्यथा लंबाई की गणना फ्रेम के पहले कॉलम के लिए की जाती है, और फिर एक्सेल में पहले कॉलम पर लागू किया जाता है, जो कि शायद सूचकांक है।
ac24

1
किसी को भी इस उत्तर की तलाश में enumerate(df)होने के enumerate(df.columns)बाद से, आपको प्रत्येक कॉलम में पुनरावृत्ति करना चाहिए df
डासेंज़ेफ़

2
@Dascienz उसी तरह से (जो आपको मैन्युअल रूप से कहने की ज़रूरत नहीं है ) dictमें कुंजियों पर पुनरावृति करता है, स्तंभों पर पुनरावृत्तियों पर पुनरावृत्ति करता है। आपको मैन्युअल रूप से पुनरावृति करने की आवश्यकता नहीं है । dictdict.keys()pd.DataFramedf.columns
अलीचौड्री

28

मैं इसे पोस्ट कर रहा हूं क्योंकि मैं बस एक ही मुद्दे में भाग गया और पाया कि Xlsxwriter और पांडा के लिए आधिकारिक दस्तावेज अभी भी इस कार्यक्षमता को असमर्थित के रूप में सूचीबद्ध है। मैं एक समाधान है कि समस्या मैं हल कर रहा था एक साथ काट दिया। मैं मूल रूप से प्रत्येक कॉलम के माध्यम से केवल पुनरावृति करता हूं और स्तंभ की चौड़ाई == उस कॉलम की सामग्री की अधिकतम लंबाई निर्धारित करने के लिए वर्कशीट.सेट_कैल्यूम का उपयोग करता हूं।

एक महत्वपूर्ण नोट, हालांकि। यह समाधान कॉलम हेडर के अनुरूप नहीं है, बस कॉलम मान। यदि आपको इसके बजाय शीर्षकों को फिट करने की आवश्यकता है, तो एक आसान बदलाव होना चाहिए। आशा है कि यह किसी की मदद करता है :)

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
अच्छा समाधान। मुझे पसंद है कि आपने दूसरे पैकेज के बजाय पंडों का उपयोग कैसे किया।

मुझे लगता है कि आपको ()अधिकतम फ़ंक्शन के अंदर की आवश्यकता है: `अधिकतम (कॉलम_लेन (), लेन (कॉल)) +
2`

21

संभवत: इसे अभी करने का कोई स्वचालित तरीका नहीं है, लेकिन जैसा कि आप ओपनपीएक्सएल का उपयोग करते हैं, निम्न पंक्ति ( मैन्युअल रूप से कैसे करें पर उपयोगकर्ता बुफ्के द्वारा एक और उत्तर से अनुकूलित ) आपको एक सेंस वैल्यू (वर्ण चौड़ाई में) निर्दिष्ट करने की अनुमति देता है:

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

डिफ़ॉल्ट ExcelWriter इंजन पांडा का उपयोग 2013 से बदलकर Xlsxwriter कर दिया गया है, जिसमें column_dimensionsविशेषता नहीं है । यदि आप ओपनपीक्सल का उपयोग करते रहना चाहते हैं, तो लेखक द्वारा उपयोग करते समय इसे केवल निर्दिष्ट करेंpd.ExcelWriter(excel_filename, engine='openpyxl')
ojdo

@ सुनील: Xlsxwriterआज के डिफ़ॉल्ट इंजन के साथ कॉलम की चौड़ाई को कैसे निर्दिष्ट करें यह देखने के लिए इंजन के रूप में उपयोग करके अन्य उत्तरों की जांच करें ।
ओजदो

21

एक अच्छा पैकेज है जिसे मैंने हाल ही में स्टाइलफ्रेम नाम से इस्तेमाल करना शुरू किया है।

यह 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प्रलेखन देखें ।

अद्यतन २

यहां कोड का एक नमूना है जो स्टाइलफ्रेम 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 पैकेज का उपयोग करना आसान हो सकता है, लेकिन मैं यह नहीं देखता कि "डिफ़ॉल्ट रूप से कॉलम की चौड़ाई ऑटो-समायोजन कैसे होती है"। जब मैं आपके द्वारा दिए गए कोड नमूने को चलाता हूं, तो सभी कॉलम एक ही चौड़ाई के होते हैं, और सभी तीन हेडर लिपटे होते हैं। आपका नमूना डेटा भी खराब तरीके से चुना गया है, क्योंकि वे सभी लगभग समान रूप से स्वाभाविक रूप से हैं। स्वचालित समायोजन को वास्तव में समझाने के लिए, आपको कुछ विस्तृत डेटा और कुछ संकीर्ण डेटा का चयन करना चाहिए। जब मैं अपने लिए ऐसा करता हूं, तो कॉलम की चौड़ाई अभी भी पहले जैसी ही होती है। जो भी समायोजन हुआ था।
जॉन वाई

शायद स्टाइलफ्रैम के इतिहास में एक बिंदु पर, कॉलम की चौड़ाई स्वचालित रूप से डिफ़ॉल्ट रूप से समायोजित की गई थी, लेकिन कम से कम आज, आपको उस कॉलम या कॉलम को निर्दिष्ट करना होगा जिसे आप best_fitपैरामीटर में समायोजित करना चाहते हैं । इसके अलावा, जब मैंने यह कोशिश की, तो मुझे बहुत खराब परिणाम मिले
जॉन वाई

चौड़ाई 1 कॉलम से दूर लगती है। मैंने indexपैरामीटर को सक्षम और अक्षम करने का प्रयास किया लेकिन कोई पासा नहीं।

1
धन्यवाद! खोज करने वालों के लिए: आप हेडर के लिए और अधिक स्टाइल कैसे जोड़ सकते हैं उदाहरण के लिए: sf.apply_headers_style(Styler(bold=False))मुझे यह पता लगाने में बहुत समय लगा। और आयात बयान में from StyleFrame import StyleFrame, Styler। यहां बोल्ड के अलावा सभी विकल्प हैं: styleframe.readthedocs.io/en/2.0.5/…
निखिल वीजे

1
@ संस्करण 3 के रूप में from styleframe import StyleFrameहागबर्ड पीईपी 8 नाम सम्मेलनों के अनुपालन के लिए आयात होना चाहिए
14

11

पांडा और xlsxwriter का उपयोग करके आप अपना कार्य कर सकते हैं, नीचे कोड पूरी तरह से पायथन 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()

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

काम पर, मैं हमेशा फ़ाइलों को एक्सेल करने के लिए डेटाफ्रेम लिख रहा हूं। इसलिए एक ही कोड को बार-बार लिखने के बजाय, मैंने एक मापांक बनाया है। अब मैं इसे आयात करता हूं और इसे एक्सेल फाइलों को लिखने और तैयार करने के लिए उपयोग करता हूं। एक नकारात्मक पक्ष यह है कि डेटाफ़्रेम अतिरिक्त बड़ा होने में लंबा समय लगता है। तो यहाँ कोड है:

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' ऑब्जेक्ट में कोई विशेषता नहीं है 'to_excel'। यह "dataframe_list" जिस तरह से बनाया गया है, उसके साथ कुछ करना है। मेरा एक सूची है जिसमें 6
डेटाफ्रेम

हां, "डेटाफ्रेम_लिस्ट" में डेटाफ्रेम होना चाहिए न कि डेटाफ्रेम नाम।
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
कोड केवल उस प्रश्न का उत्तर नहीं देते हैं जो आपको कुछ स्पष्टीकरण जोड़ना है या समय लेना है और प्रलेखन के बारे में पढ़ना है कि मैं एक अच्छा उत्तर कैसे लिखूं?
गाद

1
नमस्कार! हालांकि यह कोड प्रश्न को हल कर सकता है, जिसमें यह भी बताया गया है कि यह समस्या कैसे और क्यों हल करती है, इससे वास्तव में आपके पोस्ट की गुणवत्ता को बेहतर बनाने में मदद मिलेगी, और शायद अधिक वोट भी मिलेंगे। याद रखें कि आप भविष्य में पाठकों के लिए सवाल का जवाब दे रहे हैं, न कि केवल उस व्यक्ति से जो अब पूछ रहा है। कृपया स्पष्टीकरण जोड़ने के लिए अपने उत्तर को संपादित करें और संकेत दें कि क्या सीमाएँ और मान्यताएँ लागू होती हैं।
ब्रायन

0

हां, कॉलम चौड़ाई को समायोजित करने के लिए xlsx फ़ाइल के तथ्य के बाद आप कुछ कर सकते हैं। स्वतः भरण कॉलम के लिए xlwings का उपयोग करें । यह एक बहुत ही सरल समाधान है, उदाहरण कोड की छह अंतिम पंक्तियों को देखें। इस प्रक्रिया का लाभ यह है कि आपको फ़ॉन्ट आकार, फ़ॉन्ट प्रकार या कुछ और के बारे में चिंता करने की आवश्यकता नहीं है। आवश्यकता: एक्सेल स्थापना।

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()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.