【问题标题】:Unzipping multiple json files from folder into pandas df将文件夹中的多个 json 文件解压缩到 pandas df
【发布时间】:2020-04-24 10:13:10
【问题描述】:

我有一个文件夹,里面装满了用 gzip 压缩的 json 文件(~10gb,主要是文本数据)。我目前的代码可以运行,但速度非常慢(想想几个小时):

from glob import glob
filenames = glob('folder_path/*')
dataframes = [pd.read_json(f, compression='gzip') for f in filenames]

我希望找到一种更快的方法来解压缩所有文件,并将每个文件保存到 pandas df 或全部保存到单个 df(此时 1 与多个 df 对我来说并不重要)。我读过zlib 但这似乎不适用于gzip 文件?我也在那里尝试了一些不同的方法,但似乎都没有,例如:

filenames = glob('folder_path/*')
jsonobjs = [gzip.open(f, 'rb') for f in filenames]

返回:

---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-12-a5a84131bb38> in <module>
      1 filenames = glob('folder_path/*')
----> 2 jsonobjs = [gzip.open(f, 'rb') for f in filenames]

<ipython-input-12-a5a84131bb38> in <listcomp>(.0)
      1 filenames = glob('folder_path/*')
----> 2 jsonobjs = [gzip.open(f, 'rb') for f in filenames]

~/anaconda3/lib/python3.7/gzip.py in open(filename, mode, compresslevel, encoding, errors, newline)
     51     gz_mode = mode.replace("t", "")
     52     if isinstance(filename, (str, bytes, os.PathLike)):
---> 53         binary_file = GzipFile(filename, gz_mode, compresslevel)
     54     elif hasattr(filename, "read") or hasattr(filename, "write"):
     55         binary_file = GzipFile(None, gz_mode, compresslevel, filename)

~/anaconda3/lib/python3.7/gzip.py in __init__(self, filename, mode, compresslevel, fileobj, mtime)
    161             mode += 'b'
    162         if fileobj is None:
--> 163             fileobj = self.myfileobj = builtins.open(filename, mode or 'rb')
    164         if filename is None:
    165             filename = getattr(fileobj, 'name', '')

OSError: [Errno 24] Too many open files: 'folder_path/d2ea1c35275b495fb73cb123cdf4fe4c'

with gzip.open(glob('folder_path/*'), 'rb') as f:
    file_content = f.read()

返回:

TypeError                                 Traceback (most recent call last)
<ipython-input-10-bd68570238cd> in <module>
----> 1 with gzip.open(glob('folder_path/*'), 'rb') as f:
      2         file_content = f.read()

TypeError: 'module' object is not callable

所以这个:

with gzip.open('single_file', 'rb') as f:
    file_content = f.read()
pd.read_json(file_content)

工作得很好,比将 compression='gzip' 传递给 pd.read_json 更快,但我不知道如何让它适用于所有文件。

编辑: 尝试了以下方法:

for file_name in glob('folder_path/*'):
     with [gzip.open(f, 'rb') for f in filenames]:
            file_name = pd.read_json(f)

但返回相同的too many open files 错误

【问题讨论】:

  • 也许试试 dask? docs.dask.org/en/latest/…
  • 我刚刚使用 pd.read_json 对一些随机生成的 gzip 压缩 JSON 文件进行了快速测试。 1000 个文件,每个文件 40 kb 的压缩数据,因此总数据量为 40 MB。解压后的大小为 120kb。当使用pd.read_json 读入每个文件时,python 内存占用增加了 5-6 MB。因此,如果您一次浏览 10 GB 的文件,这将使用大量内存。你有多少内存?我很惊讶这会为你完成。数据的最终目标是什么?这一切都需要一次处理吗?
  • @totalhack 这一切都需要立即处理。目前打开所有文件大约需要一整天,实际上我有 4 个这些文件的文件夹(总共约 40GB),最终都需要打开、转换和组合。我正在为此寻找多核或分布式解决方案,但我没有太多实际实施的经验。
  • 如果我的示例中的内存使用量对您来说甚至遥遥无期,那么您将需要几 TB 的内存来一次保存所有这些。并且您可能需要多个数据,具体取决于您将数据存储在内存中后要对数据执行的操作。如果您可以提供有关您尝试对数据做什么的更多详细信息,那将很有帮助。你必须使用熊猫吗?当您尝试使用 gzip.open 时出了什么问题?您可以拥有多个 DF 的事实向我表明,您实际上可能并不需要一次全部存储在内存中。
  • @totalhack 编辑了帖子以包含更多回溯。如果我找到了一种快速打开和转换文件的方法,但这会导致多个 dfs,我将不得不将它们合并为下一步。

标签: python json pandas gzip unzip


【解决方案1】:

我已经让 OP 完成了一些更改以解决初步回溯问题,这应该允许 OP 让这个过程在较小的数据集上运行。然而,真正的问题是数据集太大而无法真正做到这一点。由于目标是训练 LDA 模型,我建议 OP 研究支持在线学习的库,以便可以在没有不可能的内存占用的情况下构建模型。

这不是对“将多个 json 文件从文件夹解压缩到 pandas df”这个更一般的主题的答案,但这并不是真正的主要问题。以下(未经测试的)代码可以遍历文件夹中的 gzip 文件并将每个文件读入数据帧。然后concat 或根据需要处理这些数据帧。

from glob import glob
import gzip

for fname in glob('folder_path/*gz'):
    with gzip.open(fname, 'rb') as f:
        df = pd.read_json(f)

请注意,使用 pandas 对许多文件执行此操作非常慢。您最好阅读和解析原始 JSON 结构,根据需要清理/转换它们,然后在所有组合数据(或数据块​​)上形成最终的 pandas 数据帧。或者如果不是真的需要,则完全避免使用 pandas。

【讨论】:

    猜你喜欢
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多