使用Python逐块加载Excel文件而不是将整个文件加载到内存中

8
我希望能够从Excel文件(xlsx)中读取10行数据,而不需要一次性加载整个文件,因为我的一台机器(内存较低)无法完成这项任务。
我尝试使用了
import xlrd
import pandas as pd
def open_file(path):
    xl = pd.ExcelFile(path)
    reader = xl.parse(chunksize=1000)
    for chunk in reader:
        print(chunk)

看起来文件先被加载,然后被分成几个部分。

如何只读取前几行?


你显然正在使用Pandas,但还没有指定它 - 你展示了完整的代码吗? - Barnabus
1
虽然不严格遵守Pandas,我的建议是使用SFrame,它可以自动进行离线计算并且速度快。使用pip install --U sframe安装。 - Vivek Kalyanarangan
Barnabus,不需要展示更多的代码。我只想加载n行。 编辑: @VivekKalyanarangan 感谢您的回答。我会去看看的。 - Kornel
xslx 是一个压缩文件。它并不会让阅读几行变得更容易。你可以读取一个 CSV 文件吗? - Eric Duminil
很抱歉,我想帮忙,但是我不能。 - Kornel
1
你尝试过使用openpyxl的只读模式吗? - John Y
1个回答

7
由于 xlsx 文件的本质(它们基本上是一堆压缩在一起的 xml 文件),您不能在任意字节处查找并希望它是您感兴趣的工作表中第 N 行的开头。
最好的方法是使用 pandas.read_excel 函数,结合 skiprows(跳过文件顶部的行)和 skip_footer(跳过底部的行)参数。但是,这将首先将整个文件加载到内存中,然后仅解析所需的行。
# if the file contains 300 rows, this will read the middle 100
df = pd.read_excel('/path/excel.xlsx', skiprows=100, skip_footer=100,
                   names=['col_a', 'col_b'])

请注意,如果不使用 names 参数手动设置表头,则列名将是最后跳过的行。
如果您希望使用 csv,那么这是一项简单的任务,因为 csv 文件是纯文本文件。
但是,如果您真的很绝望,可以从 xlsx 存档中提取相关工作表的 xml 文件并解析它。虽然这不是一项容易的任务。
以下是表示具有单个 2 X 3 表格的工作表的示例 xml 文件。其中的 <v> 标签表示单元格的值。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
    <dimension ref="A1:B3"/>
    <sheetViews>
        <sheetView tabSelected="1" workbookViewId="0">
            <selection activeCell="C10" sqref="C10"/>
        </sheetView>
    </sheetViews>
    <sheetFormatPr defaultColWidth="11" defaultRowHeight="14.25" x14ac:dyDescent="0.2"/>
    <sheetData>
        <row r="1" spans="1:2" ht="15.75" x14ac:dyDescent="0.2">
            <c r="A1" t="s">
                <v>1</v>
            </c><c r="B1" s="1" t="s">
                <v>0</v>
            </c>
        </row>
        <row r="2" spans="1:2" ht="15" x14ac:dyDescent="0.2">
            <c r="A2" s="2">
                <v>1</v>
            </c><c r="B2" s="2">
                <v>4</v>
            </c>
        </row>
        <row r="3" spans="1:2" ht="15" x14ac:dyDescent="0.2">
            <c r="A3" s="2">
                <v>2</v>
            </c><c r="B3" s="2">
                <v>5</v>
            </c>
        </row>
    </sheetData>
    <pageMargins left="0.75" right="0.75" top="1" bottom="1" header="0.5" footer="0.5"/>
</worksheet>

问题是,它会加载整个文件,然后将其分成块。感谢您的回答,但这也不是我要找的。 - Kornel
1
@Kornel 请看我的更新答案,我添加了一些信息。 - DeepSpace
谢谢您的回答。这是一些值得知道的有用信息。我会将其标记为我的问题的答案。 - Kornel
@DeepSpace 你如何解码 xlsx 文件?它似乎是二进制的。 - Viswanath Lekshmanan
@ViswanathLekshmanan 我并没有解码任何东西。我只是从XLSX文件中提取了相关工作表的XML文件,正如我在答案中所解释的那样,它只是一个“花哨”的存档文件。例如尝试使用7zip打开其中一个文件。 - DeepSpace
t="s"时,例如第一行,该值是指向共享字符串表的基于零的索引。该表可以在xl/sharedStrings.xml中找到。 - Danny_ds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接