Panda: Mencari daftar lembar dalam file excel

144

Pandas versi baru menggunakan antarmuka berikut untuk memuat file Excel:

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

tetapi bagaimana jika saya tidak tahu lembar yang tersedia?

Sebagai contoh, saya bekerja dengan file excel lembar berikut

Data 1, Data 2 ..., Data N, foo, bar

tapi saya tidak tahu Napriori.

Apakah ada cara untuk mendapatkan daftar sheet dari dokumen excel di Pandas?

Amelio Vazquez-Reina
sumber

Jawaban:

253

Anda masih bisa menggunakan kelas ExcelFile (dan sheet_namesatribut):

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

xl.sheet_names  # see all sheet names

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

lihat dokumen untuk parse untuk opsi lainnya ...

Andy Hayden
sumber
1
Terima kasih @Andy. Bolehkah saya bertanya, apakah Pandas memuat lembar excel ExcelFile? Juga, katakanlah saya mencari daftar lembar dan memutuskan untuk memuat N dari mereka, haruskah saya pada saat itu memanggil read_excel(antarmuka baru) untuk setiap lembar, atau menempel x1.parse?
Amelio Vazquez-Reina
2
Saya pikir ExcelFile membuat file tetap terbuka (dan tidak membaca semuanya), saya pikir menggunakan parse (dan membuka file hanya sekali) paling masuk akal di sini. tbh aku merindukan kedatangan read_excel!
Andy Hayden
6
Disebutkan sebelumnya di sini , tapi saya suka menyimpan kamus DataFrames menggunakan{sheet_name: xl.parse(sheet_name) for sheet_name in xl.sheet_names}
Andy Hayden
2
Seandainya saya bisa memberi Anda lebih banyak upvotes, ini berfungsi di banyak versi panda juga! (tidak tahu mengapa mereka suka mengubah API begitu sering) Terima kasih telah menunjukkan saya pada fungsi parse, inilah tautan saat ini: pandas.pydata.org/pandas-docs/stable/generated/…
Ezekiel Kruglick
3
@NicholasLu downvote tidak perlu, jawaban ini dari 2013! Yang mengatakan, sementara ExcelFile adalah cara asli untuk mem-parsing file excel itu tidak ditinggalkan dan tetap merupakan cara yang sah untuk melakukan ini.
Andy Hayden
37

Anda harus secara eksplisit menentukan parameter kedua (sheetname) sebagai Tidak Ada. seperti ini:

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

"df" semuanya sheet sebagai kamus DataFrames, Anda dapat memverifikasinya dengan menjalankan ini:

df.keys()

hasil seperti ini:

[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']

silakan merujuk panda doc untuk detail lebih lanjut: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_excel.html

Nicholas Lu
sumber
3
Ini tidak perlu mem-parsing setiap lembar sebagai DataFrame, yang tidak diperlukan. "Cara membaca file xls / xlsx" adalah pertanyaan yang berbeda .
Andy Hayden
7
@AndyHayden mungkin tidak efisien, tetapi mungkin yang terbaik jika Anda peduli dengan semua sheet, atau Anda tidak peduli dengan overhead tambahan.
CodeMonkey
8

Ini adalah cara tercepat yang saya temukan, terinspirasi oleh jawaban @ divingTobi. Semua Jawaban berdasarkan xlrd, openpyxl, atau panda lambat bagi saya, karena mereka semua memuat seluruh file terlebih dahulu.

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")]

LAUT
sumber
3

Membangun jawaban @dhwanil_shah, Anda tidak perlu mengekstrak seluruh file. Dengan zf.openitu dimungkinkan untuk membaca dari file zip langsung.

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

Dua berturut-turut readlinejelek, tetapi konten hanya di baris kedua teks. Tidak perlu menguraikan seluruh file.

Solusi ini tampaknya jauh lebih cepat daripada read_excelversi, dan kemungkinan besar juga lebih cepat daripada versi ekstrak penuh.

divingTobi
sumber
Tidak, .xls adalah format file yang sama sekali berbeda, jadi saya tidak berharap kode ini berfungsi.
divingTobi
2

Saya telah mencoba xlrd, panda, openpyxl dan pustaka-pustaka semacam itu dan semuanya sepertinya memerlukan waktu yang eksponensial karena ukuran file bertambah ketika membaca seluruh file. Solusi lain yang disebutkan di atas di mana mereka menggunakan 'on_demand' tidak berfungsi untuk saya. Jika Anda hanya ingin mendapatkan nama sheet pada awalnya, fungsi berikut berfungsi untuk file 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

Karena semua xlsx pada dasarnya adalah file zip, kami mengekstrak data xml yang mendasarinya dan membaca nama lembar dari buku kerja secara langsung yang membutuhkan sepersekian detik dibandingkan dengan fungsi perpustakaan.

Benchmarking: (Pada file xlsx 6mb dengan 4 lembar)
Panda, xlrd: 12 detik
openpyxl: 24 detik
Metode yang diusulkan: 0,4 detik

Karena kebutuhan saya hanya membaca nama lembar, overhead yang tidak perlu dari membaca sepanjang waktu mengganggu saya jadi saya mengambil rute ini sebagai gantinya.

Dhwanil shah
sumber
Apa modul yang Anda gunakan?
Daniel
@Daniel Saya hanya menggunakan zipfilemodul bawaan dan xmltodictyang saya gunakan untuk mengubah XML menjadi kamus yang mudah diubah. Meskipun Anda dapat melihat jawaban @ divingTobi di bawah ini di mana Anda dapat membaca file yang sama tanpa benar-benar mengekstraksi file di dalamnya.
Dhwanil shah
Ketika saya mencoba openpyxl dengan flag read_only secara signifikan lebih cepat (200X lebih cepat untuk file 5 MB saya). load_workbook(excel_file).sheetnamesrata-rata 8,24 di mana load_workbook(excel_file, read_only=True).sheetnamesrata-rata 39,6 ms
flutefreak7
0
from openpyxl import load_workbook

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

Untuk file Excel 5MB saya bekerja dengan, load_workbooktanpa read_onlybendera mengambil 8,24s. Dengan read_onlybendera hanya butuh 39,6 ms. Jika Anda masih ingin menggunakan pustaka Excel dan tidak menjatuhkan ke solusi xml, itu jauh lebih cepat daripada metode yang mem-parsing seluruh file.

flutefreak7
sumber