Панди: Пошук списку аркушів у файлі excel


142

Нова версія Pandas використовує наступний інтерфейс для завантаження файлів Excel:

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

але що робити, якщо я не знаю наявних аркушів?

Наприклад, я працюю з файлами excel, які наведені нижче

Дані 1, Дані 2 ..., Дані N, колонтитул, бар

але я не знаю Nапріорі.

Чи є якийсь спосіб отримати список аркушів із документа excel у Pandas?

Відповіді:


251

Ви все ще можете використовувати клас 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. Чи можу я запитати, чи завантажує Pandas лист excel ExcelFile? Крім того, скажіть, я шукаю список аркушів і вирішую завантажити N з них, чи повинен я в цей момент зателефонувати read_excel(новий інтерфейс) для кожного аркуша чи дотримуватися його x1.parse?
Амеліо Васкес-Рейна

2
Я думаю, що ExcelFile зберігає файл відкритим (і не читає його все), я думаю, що використання синтаксичного аналізу (і відкриття файлу лише один раз) має найбільше сенс тут. tbh Я пропустив прихід read_excel!
Енді Хайден

6
Згадується , перш ніж тут , але я хотів би зберегти словник DataFrames використання{sheet_name: xl.parse(sheet_name) for sheet_name in xl.sheet_names}
Енді Hayden

2
Хочеться, щоб я міг отримати більше результатів, і це працює в декількох версіях панд! (не знаю, чому їм подобається змінювати API так часто) Дякую за те, що вказує мені на функцію розбору, ось ось поточне посилання: pandas.pydata.org/pandas-docs/stable/generated/…
Єзекіїль Круглік

3
@NicholasLu сутичка була непотрібною, ця відповідь - з 2013 року! Однак це означає, що в той час, як ExcelFile є оригінальним способом розбору файлів excel, він не є застарілим і залишається абсолютно правильним способом зробити це.
Енді Хайден

36

Ви повинні чітко вказати другий параметр (ім'я аркуша) як None. подобається це:

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

див. pandas doc для отримання більш детальної інформації: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_excel.html


3
Це необгрунтовано аналізує кожен аркуш як DataFrame, що не потрібно. "Як прочитати файл xls / xlsx" - це інше питання .
Енді Хайден

7
@AndyHayden це може бути неефективно, але це може бути найкраще, якщо ви дбаєте про всі аркуші, або вам не байдуже додаткові накладні витрати.
CodeMonkey

8

Це найшвидший спосіб, який я знайшов, натхненний відповіддю @ дайвінгТобі. Усі відповіді на основі 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 s некрасиві, але зміст є лише у другому рядку тексту. Не потрібно розбирати весь файл.

Це рішення виглядає набагато швидше, ніж read_excelверсія, і, швидше за все, також швидше, ніж версія повного вилучення.


Ні, .xls - це зовсім інший формат файлу, тому я б не очікував, що цей код працює.
дайвінгТобі

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 та читаємо назви аркушів із робочої книги безпосередньо, що займає частку секунди порівняно з функціями бібліотеки.

Бенчмаркінг: (у файлі
xmbx розміром 6 Мб з 4 аркушами) Панди, xlrd: 12 секунд
openpyxl: 24 секунди
Пропонований метод: 0,4 секунди

Оскільки моя вимога полягала лише в тому, щоб прочитати назви аркушів, непотрібні витрати на читання весь час клопіли мене, тому я взяв цей маршрут замість цього.


Які модулі ви використовуєте?
Даніель

@Daniel Я використовував лише те, zipfileщо є вбудованим модулем, і xmltodictякий я використовував для перетворення XML у легко ітерабельний словник. Хоча ви можете подивитись відповідь на @vingTobi нижче, де ви можете прочитати той самий файл, фактично не вилучаючи файли всередині.
Dhwanil shah

Коли я спробував openpyxl з прапором read_only, він значно швидше (на 200 разів швидше для мого файлу 5 Мб). load_workbook(excel_file).sheetnamesв середньому 8,24, де в load_workbook(excel_file, read_only=True).sheetnamesсередньому 39,6 мс.
flutefreak7

0
from openpyxl import load_workbook

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

Для файлу Excel 5 МБ, з яким я працюю, load_workbookбез read_onlyпрапора знадобилося 8,24 секунди. З read_onlyпрапором знадобилося лише 39,6 мс. Якщо ви все ще хочете використовувати бібліотеку Excel і не переходити до рішення xml, це набагато швидше, ніж методи, які аналізують весь файл.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.