python 数据读取方式以及时间比较
先前一直在做汽车项目的数据 Pipeline 搭建,目前终于告一段落,于是打算将这段期间的工作做个总结,整理自身的最佳实践外,也希望能够帮助到有相同需求的读者们。
这篇博客主要介绍几类常见的数据读取方式以及时间比对,json、jsonlines、csv、tsv、pandas 等。后续如果接触到更多的存储形式,则会继续完善这篇博客。需要注意的是,我仅站在使用者的角度去度量这些数据读取方式,对于其内部的运行原理则没有完整的了解,如有错误请麻烦各种大佬不吝指出。
首先,我准备了一批数据,将这批数据分别存储为 json、jsonl、csv、hdf5。
接下来,在 jupyter 中测试 json、jsonlines、pandas、vaex 这四个包的数据读取速度。
json 读取
首先,导入 json 包。
1 | import json |
然后,读取 dataset_test.json 文件。
1 | %%time |
jsonlines 读取
首先,导入 jsonlines 包。
1 | import jsonlines |
然后,读取 dataset_test.jsonl 文件。
1 | %%time |
可以看到 jsonlines 的读取速度要快于 json,且 dataset_test.jsonl 文件的大小也略小于 dataset_test.json 文件,这主要是因为 jsonlines 文件相当于 json 文件中移除了 list 的括号和各列表元素的逗号。
- jsonlines:
1 | {"name": "jsonlines", "msg": "hello world!"} |
- json:
1 | [ |
jsonlines 可以在数据读写时做更精细的操作,因为 jsonlins 是一行行数据写入,这一点在错误处理时非常优秀,尤其是在大批量数据写入时。如果写入的数据有错误,使用 json.dump 会报错,无法写入,此时就会前功尽弃。而使用 jsonlines 时,我们可以加入 try except,跳过错误的数据。
【示例】:jsonlines 数据写入。
1 | error_data_list = [] |
此外,如果存储在 linux 系统上,我们可以直接也能够 wc -l 去统计 jsonlines 文件的数据量,而 json 文件则需要读取后通过 len(dataset) 的方式去获取数据量。
但是在存储的数据格式上 json 要比 jsonlines 更广泛,例如有这样一个结构的数据:
1 | { |
此时,jsonlines 就不适合了。因此,json 和 jsonlines 各有所长,在使用时需要考虑存储数据的结构。
pandas 读取
首先,导入 pandas 包。
1 | imort pandas as pd |
然后,分别使用 read_csv() 读取 dataset_test.csv 和 read_json() 读取 dataset_test.json。
1 | %%time |
可以看到 pandas 无论读取 csv 还是 json 文件速度都非常快,远快于标准 json 和 jsonlines 包的读取速度。
刚才讲了那么多 jsonlines 的优点,那么如何使用 pandas 读取 jsonlines 文件呢?我们可以将 jsonlines 视作一张表。
1 | %%time |
可以看到读取 jsonlines 的速度比读取 json 和 csv 文件更快!
其主要原因在于 read_table() 读取 jsonlines 时将其视作一个整体,而 read_json() 将 json 中每一个字段都读取了出来,因此花费更多的时间。
vaex 读取
vaex 是用于惰性核心数据框架(类似于 Pandas)的 Python 库,用于可视化和探索大型表格数据集。
- 官方 API 文档:https://vaex.readthedocs.io/en/latest/index.html
- GitHub 地址:https://vaex.readthedocs.io/en/latest/index.html
首先,导入 vaex 包(下载方式可参考官方文档)。
1 | import vaex |
然后,使用 from_csv() 读取 dataset_test.csv 文件。
1 | %%time |
天呐!这也太慢了吧,试试其他的 API。
1 | %%time |
我的天,竟然还是这么慢!这和它说的不一样呀,仔细看了下 open() 的文档说明:
Vaex supports streaming in hdf5 files from Amazon AWS object storage S3. Files are by default cached in $HOME/.vaex/file-cache/s3 such that successive access is as fast as native disk access
大意是说:vaex 支持 hdf5 文件的流式传输,默认情况下文件缓存在 $HOME/.vaex/file-cache/s3 中,连续访问与本地磁盘访问一样快。
对代码进行修改:
1 | %%time |
跑完之后再执行一次。
【注意】:from_csv() 返回的是 vaex.dataframe.DataFrameArrays,而 open() + hdf5 返回的是 vaex.hdf5.dataset.Hdf5MemoryMapped。
无论是 vaex.dataframe.DataFrameArrays 还是 vaex.hdf5.dataset.Hdf5MemoryMapped,都支持 to_pandas_df() 方法,转换为 pandas DataFrame。
对于 vaex 操作不熟悉,可以将其转换为 pandas。综合读取 hdf5 文件以及转换为 pandas 总共 3s 不到!除了第一次缓存为 hdf5 文件需要大量时间外,其它都很完美,可谓是一次“受苦”,“终身”受益。
总结
对于不同的需求场景,我们需要视情况来选择存储和读取的策略。
- 单次使用:推荐使用 pandas,如果对 pandas 的操作不熟悉,也可以通过 df.values.tolist() 的方式转换为标准的 Python List。
- 超大数据:推荐使用 vaex。
- 多次使用:推荐使用 vaex。