前言

项目中遇到客户已经下载下来的【20M-10G】大的CSV数据需要pandas处理建模,在pandas加载发现加载速度很慢,直接读取有时甚至会超出内存测试网上提到的一些加速处理方法,在此汇总记录(由于参考其他文章时,未及时记录,如有侵权联系删除)。


一、测试环境

windows10、pandas版本: 1.5.3、12th Gen Intel® Corei5-12600KF 3.70 GHz、RAM16GB

二、pandas中的read_csv读取速度测试

1.引入

import pandas as pd
import time
from sys import getsizeof

2.测试

time_start = time.time()
data = pd.read_csv("../data/input/test_data.csv", encoding="gbk",engine="python") 
time_end = time.time()
print("耗时{}秒".format(time_end - time_start))
print("数据共{}kB".format(round(getsizeof(data) / 1024, 2)))

输出结果为:

耗时27.383215188980103数据1591406.19kB

三、pandas中的read_csv提速方法

1.使用”C”引擎

time_start = time.time()
data = pd.read_csv("../data/input/test_data.csv", encoding="gbk",engine="c") 
time_end = time.time()
print("耗时{}秒".format(time_end - time_start))
print("数据共{}kB".format(round(getsizeof(data) / 1024, 2)))

输出结果为:

耗时5.371628665924072秒
数据共1591406.19kB

read_csv 中的c引擎比python引擎快5倍左右!

2.read_csv读取数据指定数据格式

pandas整数默认使用int64,浮点数使用float64,对于一些数据我们可以读取指定合适的存储数据格式,不仅可以提高读取的速度,还可以减小内存

data = pd.read_csv("../data/input/test_data.csv", encoding="gbk", engine="c")
print(data.dtypes)

输出结果为:

测试1     object
测试2     object
测试3      int64
测试4     object
测试5    float64
测试6      int64
测试7    float64
测试8    float64
dtype: object

read_csv设置dtype参数

time_start = time.time()
data = pd.read_csv("../data/input/test_data.csv", encoding="gbk",engine="c",
dtype = {"测试3": np.int8, "测试5": np.float16, "测试6": np.int8, "测试7": np.float16, "测试8": np.float16}) 
time_end = time.time()
print("耗时{}秒".format(time_end - time_start))
print("数据共{}kB".format(round(getsizeof(data) / 1024, 2)))

输出结果为:

测试1            object
测试2            object
测试3              int8
测试4            object
测试5           float16
测试6              int8
测试7           float16
测试8           float16
dtype: object
耗时5.005128908157349秒
数据共1441526.0kB

3.read_csv读取数据时使用usecols参数只加载需要的数据

时候文件中的数据并不是全部需要,这时候我们可以只加载需要的数据,这样不仅可以提高加载速度,还可以减少内存占用。当数据量特别大时,我们可以使用read_csv中的chunksize参数先读取部分数据,显示数据字段名然后使用usecols参数进行有选择的加载数据。

data = pd.read_csv("../data/input/test-data.csv",encoding="gbk", engine="c", chunksize=30)
for part_data in data:
    print(part_data.columns)
    break

输出结果为:

Index(['测试1', '测试2', '测试3', '测试4', '测试5', '测试6', '测试7', '测试8'], dtype='object')

根据需要的字段名,只加载需要的数据

time_start = time.time()
data = pd.read_csv("../data/input/test-data.csv",encoding="gbk", engine="c", usecols=["测试1"])
time_end = time.time()
print("耗时{}秒".format(time_end - time_start))
print("数据共{}kB".format(round(getsizeof(data) / 1024, 2)))

输出结果为:

耗时3.5131638050079346秒
数据共355965.88kB

可以看到加载速度和占用内存都大大减小。

四、利用第三方库进行提速

1.使用polars库读取文件

1.1 polars安装

pip install polars

1.2 polars读取数据测试

import time
import polars as pl
from sys import getsizeof

time_start = time.time()
data = pl.read_csv("../data/input/test-data.csv", encoding="utf8-lossy")
end_time = time.time()
print("耗时{}秒".format(end_time - time_start))
print(type(data))
print(data.dtypes)
print(data)
print("data对象共{}kB".format(round(getsizeof(data) / 1024, 2)))
pandas_df = data.to_pandas()
memory_usage_bytes = pandas_df.memory_usage(deep=True).sum()
memory_usage_kb = round(memory_usage_bytes / 1024, 2)  
print("数据共{}KB".format(memory_usage_kb))

输出结果为:

耗时0.07973313331604004<class 'polars.dataframe.frame.DataFrame'>
[Int64, Utf8, Utf8, Int64, Utf8, Float64, Int64, Float64, Float64]
shape: (186_958, 9)
┌────────┬─────────────────────┬─────────────────────┬───────┬───┬────────┬───────┬───────┬───────┐
│        ┆ ����1               ┆ ����2               ┆ ����3 ┆ … ┆ ����5  ┆ ����6 ┆ ����7 ┆ ����8 │
│ ------------   ┆   ┆ ------------   │
│ i64    ┆ strstr                 ┆ i64   ┆   ┆ f64    ┆ i64   ┆ f64   ┆ f64   │
╞════════╪═════════════════════╪═════════════════════╪═══════╪═══╪════════╪═══════╪═══════╪═══════╡
│ 02023-03-09 00:00:002023-03-09 01:00:00205   ┆ … ┆ 1.123630.010.23  │
│ 12023-03-09 00:00:002023-03-09 01:00:00201   ┆ … ┆ 0.000.00.0   │
│ 22023-03-09 00:00:002023-03-09 01:00:00202   ┆ … ┆ 0.000.00.0   │
│ 32023-03-09 00:00:002023-03-09 01:00:00203   ┆ … ┆ 0.194720.00.01  │
│ …      ┆ …                   ┆ …                   ┆ …     ┆ … ┆ …      ┆ …     ┆ …     ┆ …     │
│ 1869542023-06-05 22:00:002023-06-05 23:00:0019    ┆ … ┆ 0.117240.00.01  │
│ 1869552023-06-05 22:00:002023-06-05 23:00:0020    ┆ … ┆ 0.4344180.00.04  │
│ 1869562023-06-05 22:00:002023-06-05 23:00:0021    ┆ … ┆ 1.0528210.010.07  │
│ 1869572023-06-05 22:00:002023-06-05 23:00:0022    ┆ … ┆ 0.6484170.010.16  │
└────────┴─────────────────────┴─────────────────────┴───────┴───┴────────┴───────┴───────┴───────┘
data对象0.05kB
数据共67628.84KB

Process finished with exit code 0

从测试结果看同一份数据polars读取数据速度比pandas中的read_csv快将近50倍! ! !。

在使用polars直接读取数据时候时候报错

exceptions.ComputeError: invalid utf-8 sequence in csv

这个错误可以在polars读取数据时候将encoding参数设置成”utf8-lossy“,这样一些无法编码字符会使用代替。

data = pl.read_csv("../data/input/test-data.csv", encoding="utf8-lossy")

2. datatable读取数据测试

2.1 datatable安装

pip install datatable

2.2 datatable测试

import time
import datatable as dt
from sys import getsizeof


time_start = time.time()
data = dt.fread("../data/input/test-data.csv", encoding="gbk")
end_time = time.time()
print("耗时{}秒".format(end_time - time_start))
print("datatable版本:", dt.__version__)
print(type(data))
print("数据共{}kB".format(round(getsizeof(data) / 1024, 2)))

输出结果为:

耗时0.11500072479248047秒
datatable版本: 1.0.0
<class 'datatable.Frame'>
数据共22585.8kB

从测试结果来看datatable读取数据的速度和polars差不多。

安装datatable时,遇到下面错误,经查看datatable文档https://datatable.readthedocs.io/en/latest/releases/v1.0.0.html,1.0.0版本的datatable支持python版本为python3.9、python3.8、python3.7、python3.6,我的python版本为python3.10,降低python版本成功安装,若遇到相同错误可查看datatable文档查看最新版的datatable支持python版本。

Collecting datatable
  Using cached datatable-1.0.0.tar.gz (1.1 MB)
  Getting requirements to build wheel ... done
  Preparing metadata (pyproject.toml) ... error
  error: subprocess-exited-with-error

  × Preparing metadata (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [22 lines of output]
      Traceback (most recent call last):
        File "D:ancondalibsite-packagespip_vendorpyproject_hooks_in_process_in_process.py", line 353, in <module>
          main()
        File "D:ancondalibsite-packagespip_vendorpyproject_hooks_in_process_in_process.py", line 335, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
        File "D:ancondalibsite-packagespip_vendorpyproject_hooks_in_process_in_process.py", line 152, in prepare_metadata_for_build_wheel
          whl_basename = backend.build_wheel(metadata_directory, config_settings)
        File "C:UsersAdministratorAppDataLocalTemppip-install-r7zihkkbdatatable_259142d33cfc4c0cb26d395c8dfed6fdciext.py", line 573, in build_wheel
          generate_build_info(flavor, strict=not is_source_distribution())
        File "C:UsersAdministratorAppDataLocalTemppip-install-r7zihkkbdatatable_259142d33cfc4c0cb26d395c8dfed6fdciext.py", line 467, in generate_build_info
          git_hash = shell_cmd(["git", "rev-parse", "HEAD"], strict=strict)
        File "C:UsersAdministratorAppDataLocalTemppip-install-r7zihkkbdatatable_259142d33cfc4c0cb26d395c8dfed6fdciext.py", line 437, in shell_cmd
          return subprocess.check_output(cmd, universal_newlines=True,
        File "D:ancondalibsubprocess.py", line 421, in check_output
          return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
        File "D:ancondalibsubprocess.py", line 503, in run
          with Popen(*popenargs, **kwargs) as process:
        File "D:ancondalibsubprocess.py", line 971, in __init__
          self._execute_child(args, executable, preexec_fn, close_fds,
        File "D:ancondalibsubprocess.py", line 1440, in _execute_child
          hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
      FileNotFoundError: [WinError 2] 系统找不到指定文件[end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

× Encountered error while generating package metadata.
╰─> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.

3. dask读取数据测试

pandas官方pandas文档推荐一个并行处理级别数据的库dask,该库采用并行的方法,可快速处理大量数据,更多使用方法大家可以查看pandas文档里面有更详细的案例介绍和使用方法介绍

3.1 dask安装

pip install dask

3.2 dask读取数据测试

import time
import dask
import dask.dataframe as dd
from sys import getsizeof


time_start = time.time()
data = dd.read_csv("../data/input/test-data.csv", encoding="gbk")
end_time = time.time()
print("耗时{}秒".format(end_time - time_start))
print("dask版本:", dask.__version__)
print(type(data))
print("data对象共{}kB".format(round(getsizeof(data) / 1024, 2)))
print("数据共{}kB".format(round(getsizeof(data.head(len(data)-1)) / 1024, 2)))
print(data)

输出结果为:

耗时0.005980253219604492秒
dask版本: 2023.6.0
<class 'dask.dataframe.core.DataFrame'>
data对象0.05kB
数据共64114.47kB
Dask DataFrame Structure:
              Unnamed: 0     测试1     测试2    测试3     测试4      测试5    测试6      测试7      测试8
npartitions=1                                                                            
                   int64  object  object  int64  object  float64  int64  float64  float64
                     ...     ...     ...    ...     ...      ...    ...      ...      ...
Dask Name: read-csv, 1 graph layer

Process finished with exit code 0

从测试结果看dask读取数据的速度将近read_csv的1000倍,datatable和polars的20倍!!!!,速度惊人!!

五、经验总结

1、工作中若是无法要求数据保存格式,当遇到较大数据量级的数据需要采用python进行建模处理时,对于csv文件可以使用dask、polars、datatable等第三方库进行协助操作,另外pandas库中相关函数参数设置也可以提高我们数据读取的速度。
2、如果对数据的保存格式有自主权,可尝试pickle、hdf5格式、极其不建议存成xlsx格式,本人测试该格式数据读取速度非常慢!!!。
欢迎相关小伙伴进群交流学习qq群:865416910

原文地址:https://blog.csdn.net/a347604678/article/details/131216825

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_23666.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注