1

我想尝试使用 uproot 将一些带有平面 ROOT NTupels 的根文件读入桌面框架。214 个文件,每个 500kb,每个大约 8000 行和 16 列/变量。它们很容易适应内存中的 pandas 数据框,但我正在尝试学习 dask(和 uproot,以前只使用 root_pandas),因为我希望将来会有更大的数据集。

所以我认为这uproot.daskframes(list_of_paths, flatten=True)将是把文件读入桌面框架的工具。很好地创建框架,但在以下Too many open files错误中计算它:https://pastebin.com/mfHgB16Q。当我将文件限制为例如 100 个时,它的计算工作但很慢(30 秒),在少数文件上,没问题。当我使用 100 个文件并增加篮子(例如 100Mb)以提高速度时,我得到一个RecursionErrorhttps ://pastebin.com/xTHa1Wav

我自己的解决方案是创建带有连根拔起的普通熊猫数据框,延迟创建并使用 dask 创建连接它们,这对我来说效果很好,并且比uproot.daskframes大量文件的计算速度更快。

import uproot
from dask import delayed
import dask.dataframe as dd

def daskframe_from_rootfiles(path_list, treepath, branches=None):
    @delayed
    def get_df(file, treepath=None, branches=None):
        tree = uproot.open(file)[treepath]
        return tree.pandas.df(branches=branches)

    dfs = [get_df(path, treepath, branches=branches) for path in path_list]
    daskframe = dd.from_delayed(dfs)
    return daskframe

延迟数据帧创建的好处是我可以使用 dask 来并行化它。

但我觉得应该有一些规范的方式,可能是我缺少的东西,也许还有其他选项我应该用于该daskframes功能,或者我应该完全使用其他功能来做到这一点。你能帮我有什么想法吗或最佳实践?

4

2 回答 2

2
    @delayed
    def get_df(file, treepath=None, branches=None):
        tree = uproot.open(file)[treepath]
        return tree.pandas.df(branches=branches)

我的猜测是这个函数留下了一个打开的文件句柄。也许有一些方法可以在打开后关闭文件?

    @delayed
    def get_df(filename, treepath=None, branches=None):
        file = uproot.open(filename)
        tree = file[treepath]
        df = tree.pandas.df(branches=branches)
        file.close()  # does something like this exist?
        return df
于 2020-02-15T22:23:46.463 回答
1

Jim Pivarski 的评论证实了我的方法是可以的,这不是我做的完全错误的事情。由于他是开发人员,因此我不希望得到更复杂的答案,因此我将其标记为 ansered。

编辑:直到 2 天过去,我才能将自己的答案标记为解决方案,所以我会等到那时或其他人发布答案。

于 2020-02-12T14:56:21.263 回答