Panda: cercare l'elenco dei fogli in un file Excel


144

La nuova versione di Pandas utilizza la seguente interfaccia per caricare file Excel:

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

ma cosa succede se non conosco i fogli disponibili?

Ad esempio, sto lavorando con file Excel che i seguenti fogli

Dati 1, Dati 2 ..., Dati N, foo, bar

ma non conosco Na priori.

C'è un modo per ottenere l'elenco dei fogli da un documento Excel in Pandas?

Risposte:


253

Puoi ancora usare la classe ExcelFile (e l' sheet_namesattributo):

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

xl.sheet_names  # see all sheet names

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

vedere i documenti per l'analisi per ulteriori opzioni ...


1
Grazie @Andy. Posso chiedere, Panda carica il foglio Excel ExcelFile? Inoltre, supponiamo che io cerchi l'elenco dei fogli e decida di caricarne N, a quel punto dovrei chiamare read_excel(la nuova interfaccia) per ciascun foglio o attenermi a x1.parse?
Amelio Vazquez-Reina

2
Penso che ExcelFile mantenga il file aperto (e non lo legga tutto), penso che usare parse (e aprire il file solo una volta) abbia più senso qui. tbh ho perso l'arrivo di read_excel!
Andy Hayden,

6
Menzionato prima qui , ma mi piace tenere un dizionario di DataFrames usando{sheet_name: xl.parse(sheet_name) for sheet_name in xl.sheet_names}
Andy Hayden

2
Vorrei poterti dare più voti, questo funziona anche su più versioni di Panda! (non so perché gli piace cambiare così spesso l'API) Grazie per avermi indicato la funzione di analisi, ecco il link attuale: pandas.pydata.org/pandas-docs/stable/generated/…
Ezekiel Kruglick

3
@NicholasLu il downvote non è stato necessario, questa risposta è del 2013! Detto questo, mentre ExcelFile è il modo originale di analizzare i file Excel, non è deprecato e rimane un modo perfettamente valido per farlo.
Andy Hayden,

37

È necessario specificare esplicitamente il secondo parametro (nome foglio) come Nessuno. come questo:

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

"df" sono tutti fogli come un dizionario di DataFrames, puoi verificarlo eseguendo questo:

df.keys()

risultato come questo:

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

fare riferimento al documento Panda per maggiori dettagli: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_excel.html


3
Ciò analizza inutilmente ogni foglio come DataFrame, che non è necessario. "Come leggere un file xls / xlsx" è una domanda diversa .
Andy Hayden,

7
@AndyHayden potrebbe non essere efficiente, ma potrebbe essere il migliore se ti interessano tutti i fogli o non ti preoccupi dell'overhead aggiuntivo.
CodeMonkey

8

Questo è il modo più veloce che ho trovato, ispirato alla risposta di @ divingTobi. Tutte le risposte basate su xlrd, openpyxl o panda sono lente per me, poiché caricano prima l'intero file.

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

Sulla base della risposta di @dhwanil_shah, non è necessario estrarre l'intero file. Con zf.openè possibile leggere direttamente da un file zippato.

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

Le due readlines consecutive sono brutte, ma il contenuto è solo nella seconda riga del testo. Non è necessario analizzare l'intero file.

Questa soluzione sembra essere molto più veloce della read_excelversione e molto probabilmente anche più veloce della versione di estrazione completa.


No, .xls è un formato di file completamente diverso, quindi non mi aspetto che questo codice funzioni.
divingTobi

2

Ho provato xlrd, panda, openpyxl e altre librerie simili e tutte sembrano impiegare tempo esponenziale all'aumentare della dimensione del file mentre legge l'intero file. Le altre soluzioni sopra menzionate in cui hanno usato 'on_demand' non hanno funzionato per me. Se vuoi solo ottenere inizialmente i nomi dei fogli, la seguente funzione funziona per i 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

Poiché tutti gli xlsx sono sostanzialmente file compressi, estraiamo i dati xml sottostanti e leggiamo i nomi dei fogli direttamente dalla cartella di lavoro, il che richiede una frazione di secondo rispetto alle funzioni della libreria.

Benchmarking: (su un file xlsx 6mb con 4 fogli)
Panda, xlrd: 12 secondi
openpyxl: 24 secondi
Metodo proposto: 0,4 secondi

Dato che il mio requisito era solo leggere i nomi dei fogli, il sovraccarico inutile della lettura per tutto il tempo mi stava infastidendo, quindi ho preso questa strada invece.


Quali sono i moduli che stai usando?
Daniel,

@Daniel Ho usato solo zipfilequale è un modulo integrato e xmltodictche ho usato per convertire l'XML in un dizionario facilmente iterabile. Anche se puoi guardare la risposta di @ divingTobi qui sotto dove puoi leggere lo stesso file senza estrarre effettivamente i file all'interno.
Dhwanil shah,

Quando ho provato openpyxl con il flag read_only è significativamente più veloce (200 volte più veloce per il mio file da 5 MB). load_workbook(excel_file).sheetnamesmedia 8.24s dove load_workbook(excel_file, read_only=True).sheetnamesmediamente 39.6ms.
flutefreak7,

0
from openpyxl import load_workbook

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

Per un file Excel da 5 MB con cui sto lavorando, load_workbooksenza la read_onlybandiera ci sono voluti 8,24 secondi. Con la read_onlybandiera ci sono voluti solo 39,6 ms. Se desideri comunque utilizzare una libreria Excel e non passare a una soluzione XML, è molto più veloce dei metodi che analizzano l'intero file.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.