gpt4 book ai didi

python - 如何使此功能更有效地连接来自单个文件的 Excel 工作表?

转载 作者:行者123 更新时间:2023-11-28 22:26:03 26 4
gpt4 key购买 nike

我有几个 Excel 文件,我想从中生成单独的数据框,这些数据框将是每个文件中工作表的任意子集的串联。

重要的是我能够对工作表进行子集化(在这里我通过索引到 sheet_names 列表来做到这一点),并且还以某种方式跟踪出处(就像我在这里使用 assign 方法)。

此代码目前有效,但我担心我缺少一些使其更高效的基本方法(当我最终得到一个包含 20 张纸的文件时)。

我已经回顾了其他几个与连接多个 CSV 或 Excel 文件有关的问题1,但是很难将这些问题归纳为一个<中的解析工作表的问题/em> 文件,关于效率。

这个问题的部分原因是我之前使用生成器连接 Excel 文件,但我很难将这些情况推广到这个情况。

Example Excel File on GitHub

import pandas as pd
import xlrd

import xlwt

def file_parser(file):
df_list = []
for x in file.sheet_names[1::]:
df = file.parse(x).assign(Source=x)
df_list.append(df)
return df_list

1 How to parse dataframes from an excel sheet with many tables (using Python, possibly Pandas)

Import multiple csv files into pandas and concatenate into one DataFrame

Pands ExcelFile.parse() reading file in as dict instead of dataframe

最佳答案

“高效”可以有不同的解释。根据您的描述(尤其是提到生成器),我猜您的意思是内存和计算效率(使用尽可能少的内存并避免对相同数据重复循环)。有了这个想法,就开始吧:

def df_gen(filename, sheet_names):
with xlrd.open_workbook(filename, on_demand=True) as xl_file:
for sheet in sheet_names:
yield pd.read_excel(
xl_file, sheetname=sheet, engine='xlrd').assign(source=sheet)
# tell xlrd to let the sheet leave memory
xl_file.unload_sheet(sheet)

这利用了 xlrd 的 "worksheets on demand"功能以避免将整个 Excel 文档加载到内存中。在构造 DataFrame 后,工作表会从内存中显式卸载。因为它使用 yield 它是一个生成器,同时创建多少数据帧取决于您的使用情况。下面是将此生成器传递给 pandas.concat 的示例用法:

df = pd.concat(df_gen('file_name.xlsx', ['sheet1', 'sheet2']), ignore_index=True)

不过请注意,concat materializes在进行串联之前生成器中的所有内容,所以这并不一定比你建立列表的例子更有效,除了我的函数有意管理 xlrd 工作簿的资源使用。在这种情况下,我认为您最终会在内存中一次获得 1 或 2 个数据副本,具体取决于 concat 的内部结构。

如果您真的担心内存问题,您可以使用生成器一次一张地迭代构建数据框:

# create a generator
gen = df_gen(str(filename), sheet_names)

# get starting point
df = next(gen)

# iterate over the rest of the generator
for next_df in gen:
df = df.append(next_df, ignore_index=True)

我预计这在计算效率上会低于同时调用整个所需数据帧集的 concat,但我还没有研究这是否真的如此。在这种情况下,我认为您最终一次只会得到内存中所有数据的 1 个副本,再加上生成器每次循环的工作表数据的一个额外副本。

您最了解自己的情况,但除非这些是一些真正令人印象深刻的 Excel 文件,否则我不会投入大量精力来优化内存和计算,而不仅仅是看似明显的胜利。考虑到这一点,这里有一个利用 pandas.read_excel 能力的简短函数。一次阅读多张纸:

def sheets_to_df(filename, sheet_names):
df_dict = pd.read_excel(filename, sheetname=sheet_names)
return pd.concat(
(df.assign(source=sheet) for sheet, df in dfs.items()), ignore_index=True)

需要注意的一点是,当传入文件名 read_excel 时,将 load the entire Excel document (例如,不使用 xlrd 的“按需”功能)。因此,虽然这在代码行方面是高效的,但在内存方面绝对不是高效的。我认为这会短暂地以内存中的所有数据结束 2-3 次:一次在 df_dict 中,一次在最终连接的数据帧中(可能再次取决于 concat 的内部结构) >).但是一旦这个函数返回,你在最终数据框中只剩下一个副本。如果您无论如何都打算阅读大部分工作表,这不会是一个巨大的浪费(假设它们都至少两次适合内存),但如果您打算只阅读工作表的一小部分,这可能有点浪费浪费。

希望对您有所帮助!您可以在此处将其作为 Jupyter 笔记本获取:https://gist.github.com/jiffyclub/9ab668f63c3d0f9adf3e730dc37cd419

关于python - 如何使此功能更有效地连接来自单个文件的 Excel 工作表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45113070/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com