นุ่น: ค้นหารายการชีตในไฟล์ excel


166

Pandas เวอร์ชันใหม่ใช้อินเทอร์เฟซต่อไปนี้เพื่อโหลดไฟล์ Excel:

read_excel('path_to_file.xls', 'Sheet1', index_col=None, na_values=['NA'])

แต่ถ้าฉันไม่รู้ว่ามีแผ่นงานอยู่ล่ะ?

ตัวอย่างเช่นฉันกำลังทำงานกับไฟล์ excel ที่ชีตต่อไปนี้

ข้อมูล 1, ข้อมูล 2 ... , ข้อมูล N, foo, บาร์

แต่ฉันไม่รู้จักNเบื้องต้น

มีวิธีใดบ้างในการรับรายการชีตจากเอกสาร excel ใน Pandas

คำตอบ:


286

คุณยังสามารถใช้คลาสExcelFile (และsheet_namesแอตทริบิวต์):

xl = pd.ExcelFile('foo.xls')

xl.sheet_names  # see all sheet names

xl.parse(sheet_name)  # read a specific sheet to DataFrame

ดูเอกสารสำหรับการแยกวิเคราะห์สำหรับตัวเลือกเพิ่มเติม ...


1
ขอบคุณ @Andy ขอถามนุ่นโหลดแผ่น excel มาExcelFileหรือเปล่า นอกจากนี้สมมติว่าฉันค้นหารายการแผ่นงานและตัดสินใจที่จะโหลด N จากนั้นฉันควรเรียกใช้read_excel(อินเทอร์เฟซใหม่) สำหรับแต่ละแผ่นหรือx1.parseไม่?
Amelio Vazquez-Reina

2
ฉันคิดว่า ExcelFile ทำให้ไฟล์เปิดอยู่ (และไม่ได้อ่านทั้งหมด) ฉันคิดว่าการใช้การแยกวิเคราะห์ (และเปิดไฟล์เพียงครั้งเดียว) เหมาะสมที่สุดที่นี่ tbh ฉันพลาดการมาถึงของ read_excel!
Andy Hayden

6
กล่าวก่อนที่นี่แต่ผมชอบที่จะเก็บไว้ในพจนานุกรมของ DataFrames โดยใช้{sheet_name: xl.parse(sheet_name) for sheet_name in xl.sheet_names}
แอนดี้เฮย์เดน

2
หวังว่าฉันจะเพิ่มคะแนนโหวตให้คุณได้มากขึ้นสิ่งนี้ใช้ได้กับแพนด้าหลายเวอร์ชันด้วย! (ไม่รู้ว่าทำไมพวกเขาถึงชอบเปลี่ยน API บ่อยจัง) ขอบคุณที่ชี้ให้ฉันดูที่ฟังก์ชันแยกวิเคราะห์นี่คือลิงค์ปัจจุบันแม้ว่า: pandas.pydata.org/pandas-docs/stable/generated/…
Ezekiel Kruglick

3
@NicholasLu การโหวตไม่จำเป็นคำตอบนี้มาจากปี 2013! ที่กล่าวว่าในขณะที่ ExcelFile เป็นวิธีดั้งเดิมในการแยกวิเคราะห์ไฟล์ excel แต่ยังไม่เลิกใช้งานและยังคงเป็นวิธีที่ถูกต้องอย่างสมบูรณ์ในการทำเช่นนี้
Andy Hayden

40

คุณควรระบุพารามิเตอร์ที่สอง (ชื่อแผ่นงาน) อย่างชัดเจนว่าไม่มี แบบนี้:

 df = pandas.read_excel("/yourPath/FileName.xlsx", None);

"df" เป็นแผ่นงานทั้งหมดเป็นพจนานุกรมของ DataFrames คุณสามารถตรวจสอบได้โดยเรียกใช้สิ่งนี้:

df.keys()

ผลลัพธ์ดังนี้:

[u'201610', u'201601', u'201701', u'201702', u'201703', u'201704', u'201705', u'201706', u'201612', u'fund', u'201603', u'201602', u'201605', u'201607', u'201606', u'201608', u'201512', u'201611', u'201604']

โปรดดูเอกสารแพนด้าสำหรับรายละเอียดเพิ่มเติม: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_excel.html


3
ซึ่งจะแยกวิเคราะห์แผ่นงานทุกแผ่นเป็น DataFrame โดยไม่จำเป็นซึ่งไม่จำเป็น "วิธีการอ่าน / xlsx xls ไฟล์" เป็นคำถามที่แตกต่าง
Andy Hayden

8
@AndyHayden มันอาจจะไม่มีประสิทธิภาพ แต่มันอาจจะดีที่สุดถ้าคุณสนใจเกี่ยวกับแผ่นงานทั้งหมดหรือคุณไม่สนใจเกี่ยวกับค่าใช้จ่ายเพิ่มเติม
CodeMonkey

8

นี่เป็นวิธีที่เร็วที่สุดที่ฉันพบโดยได้รับแรงบันดาลใจจากคำตอบของ @ divingTobi คำตอบทั้งหมดตาม xlrd, openpyxl หรือ pandas นั้นช้าสำหรับฉันเพราะพวกเขาทั้งหมดโหลดไฟล์ทั้งหมดก่อน

from zipfile import ZipFile
from bs4 import BeautifulSoup  # you also need to install "lxml" for the XML parser

with ZipFile(file) as zipped_file:
    summary = zipped_file.open(r'xl/workbook.xml').read()
soup = BeautifulSoup(summary, "xml")
sheets = [sheet.get("name") for sheet in soup.find_all("sheet")]


3

จากคำตอบของ @dhwanil_shah คุณไม่จำเป็นต้องแตกไฟล์ทั้งหมด ด้วยzf.openมันเป็นไปได้ที่จะอ่านจากไฟล์ซิปโดยตรง

import xml.etree.ElementTree as ET
import zipfile

def xlsxSheets(f):
    zf = zipfile.ZipFile(f)

    f = zf.open(r'xl/workbook.xml')

    l = f.readline()
    l = f.readline()
    root = ET.fromstring(l)
    sheets=[]
    for c in root.findall('{http://schemas.openxmlformats.org/spreadsheetml/2006/main}sheets/*'):
        sheets.append(c.attrib['name'])
    return sheets

สองครั้งต่อเนื่องกันreadlineน่าเกลียด แต่เนื้อหาอยู่ในบรรทัดที่สองของข้อความเท่านั้น ไม่จำเป็นต้องแยกวิเคราะห์ทั้งไฟล์

ดูเหมือนว่าโซลูชันนี้จะเร็วกว่าread_excelเวอร์ชันนี้มากและส่วนใหญ่ก็เร็วกว่าเวอร์ชันเต็มด้วย


ไม่. xls เป็นรูปแบบไฟล์ที่แตกต่างไปจากเดิมอย่างสิ้นเชิงดังนั้นฉันจึงไม่คิดว่าโค้ดนี้จะใช้งานได้
DivingTobi

2

ฉันได้ลองใช้ xlrd, pandas, openpyxl และไลบรารีอื่น ๆ แล้วและดูเหมือนว่าทั้งหมดจะใช้เวลาเอ็กซ์โพเนนเชียลเนื่องจากขนาดไฟล์เพิ่มขึ้นเมื่ออ่านทั้งไฟล์ วิธีแก้ปัญหาอื่น ๆ ที่กล่าวถึงข้างต้นซึ่งพวกเขาใช้ 'on_demand' ไม่ได้ผลสำหรับฉัน หากคุณต้องการรับชื่อแผ่นงานในตอนแรกฟังก์ชันต่อไปนี้ใช้ได้กับไฟล์ xlsx

def get_sheet_details(file_path):
    sheets = []
    file_name = os.path.splitext(os.path.split(file_path)[-1])[0]
    # Make a temporary directory with the file name
    directory_to_extract_to = os.path.join(settings.MEDIA_ROOT, file_name)
    os.mkdir(directory_to_extract_to)

    # Extract the xlsx file as it is just a zip file
    zip_ref = zipfile.ZipFile(file_path, 'r')
    zip_ref.extractall(directory_to_extract_to)
    zip_ref.close()

    # Open the workbook.xml which is very light and only has meta data, get sheets from it
    path_to_workbook = os.path.join(directory_to_extract_to, 'xl', 'workbook.xml')
    with open(path_to_workbook, 'r') as f:
        xml = f.read()
        dictionary = xmltodict.parse(xml)
        for sheet in dictionary['workbook']['sheets']['sheet']:
            sheet_details = {
                'id': sheet['@sheetId'],
                'name': sheet['@name']
            }
            sheets.append(sheet_details)

    # Delete the extracted files directory
    shutil.rmtree(directory_to_extract_to)
    return sheets

เนื่องจาก xlsx ทั้งหมดเป็นไฟล์ซิปโดยทั่วไปเราจึงดึงข้อมูล xml ที่อยู่เบื้องหลังและอ่านชื่อแผ่นงานจากสมุดงานโดยตรงซึ่งใช้เวลาเพียงเสี้ยววินาทีเมื่อเทียบกับฟังก์ชันไลบรารี

Benchmarking: (บนไฟล์ 6mb xlsx ที่มี 4 แผ่น)
Pandas, xlrd: 12 วินาที
openpyxl: 24 วินาที
วิธีการเสนอ: 0.4 วินาที

เนื่องจากความต้องการของฉันเพียงแค่อ่านชื่อแผ่นงานค่าใช้จ่ายที่ไม่จำเป็นในการอ่านตลอดเวลาทำให้ฉันติดขัดดังนั้นฉันจึงใช้เส้นทางนี้แทน


คุณใช้โมดูลอะไร
Daniel

@ Daniel ฉันใช้เฉพาะzipfileซึ่งเป็นโมดูลที่สร้างขึ้นและxmltodictฉันใช้เพื่อแปลง XML เป็นพจนานุกรมที่ทำซ้ำได้อย่างง่ายดาย แม้ว่าคุณจะสามารถดูคำตอบของ @ DivingTobi ด้านล่างซึ่งคุณสามารถอ่านไฟล์เดียวกันได้โดยไม่ต้องแตกไฟล์ภายใน
Dhwanil shah

เมื่อฉันลอง openpyxl ด้วยแฟล็ก read_only มันเร็วกว่ามาก (เร็วกว่า 200 เท่าสำหรับไฟล์ 5 MB ของฉัน) load_workbook(excel_file).sheetnamesเฉลี่ย 8.24 วินาทีload_workbook(excel_file, read_only=True).sheetnamesโดยเฉลี่ย 39.6 มิลลิวินาที
flutefreak7

1
from openpyxl import load_workbook

sheets = load_workbook(excel_file, read_only=True).sheetnames

สำหรับไฟล์ Excel ขนาด 5MB ที่ฉันใช้งานload_workbookโดยไม่มีread_onlyแฟล็กใช้เวลา 8.24 วินาที ด้วยread_onlyแฟล็กใช้เวลาเพียง 39.6 มิลลิวินาที หากคุณยังต้องการใช้ไลบรารี Excel และไม่ทิ้งไปที่โซลูชัน xml จะเร็วกว่าวิธีการแยกวิเคราะห์ไฟล์ทั้งหมด


0

ถ้าคุณ:

  • ดูแลเกี่ยวกับประสิทธิภาพ
  • ไม่ต้องการข้อมูลในไฟล์ในขณะดำเนินการ
  • ต้องการไปกับไลบรารีแบบเดิมหรือการใช้โซลูชันของคุณเอง

ด้านล่างนี้ได้รับการวัดประสิทธิผลใน ~ 10Mb xlsx, xlsbไฟล์

xlsx, xls

from openpyxl import load_workbook

def get_sheetnames_xlsx(filepath):
    wb = load_workbook(filepath, read_only=True, keep_links=False)
    return wb.sheetnames

Benchmarks: ปรับปรุงความเร็วประมาณ14 เท่า

# get_sheetnames_xlsx vs pd.read_excel
225 ms ± 6.21 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
3.25 s ± 140 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

xlsb

from pyxlsb import open_workbook

def get_sheetnames_xlsb(filepath):
  with open_workbook(filepath) as wb:
     return wb.sheets

Benchmarks: ปรับปรุงความเร็ว ~ 56x

# get_sheetnames_xlsb vs pd.read_excel
96.4 ms ± 1.61 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
5.36 s ± 162 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

หมายเหตุ:

  • นี่เป็นแหล่งข้อมูลที่ดี - http://www.python-excel.org/
  • xlrd ไม่ได้รับการดูแลอีกต่อไปในปี 2020
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.