V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
jiminjohn0402
V2EX  ›  Python

Python 的大文件解析

  •  
  •   jiminjohn0402 · 178 天前 · 2600 次点击
    这是一个创建于 178 天前的主题,其中的信息可能已经有所发展或是发生改变。
    今天做了一个 3gcsv 数据量 2100 万条的 csv 拆分,因为 csv 总提示数据超长,然后就导出为 xlsx ,但是非常慢,因为是初次接触,是不是哪里有什么问题。但是如果只是拆分 csv 不会很慢(都会先按一个字段进行排序)。
    想问下各位大佬对于这一类型的数据拆分和解析如何处理,有什么优化方案?用的是 mbp 19 16g 内存 intel i7
    第 1 条附言  ·  172 天前

    大文件转为xlsx确实很慢,我自己什么不做,只是将csv拆开,然后转为xlsx,也很慢,240万数据,大概330s左右。 有4个日期字段,但是都做了预处理,感觉还是效果很小,用了engine=‘openpyxl’,仍然还是一样的速度

    import pandas as pd
    
    # 读取 CSV 文件
    chunksize = 500000  # 设置每个文件的行数
    reader = pd.read_csv('your_file.csv', chunksize=chunksize)  # 替换为你的 CSV 文件路径
    
    # 分割数据并导出为多个 Excel 文件
    file_number = 1
    for chunk in reader:
        output_file = f"output_{file_number}.xlsx"  # 设置导出文件名
        chunk.to_excel(output_file, index=False)
        file_number += 1
    
    print("数据已分割并导出为多个 Excel 文件")
    
    18 条回复    2023-11-02 16:15:03 +08:00
    l1xnan
        1
    l1xnan  
       177 天前
    没明白你那个“因为..., 然后 ...” 的因果关系。如果是读 csv 慢,用最新版本的 pandas 或者 pyarrow 或者 duckdb ,都非常快,不要自己写 open/for 循环,如果是写 xlsx 慢,格式决定写速度可优化空间不多,xlsxwriter 相比 openpyxl 性能好点,用 constant_memory=optimised 参数,内存优化非常明显,速度会比 openpyxl 库快一点
    evemoo
        2
    evemoo  
       177 天前
    一种思路
    ```python
    def list_split(source_list, n):
    return [source_list[i:i+n] for i in range(0, len(source_list), n)]

    while line := f.readline():
    do_something
    ```
    orangie
        3
    orangie  
       177 天前
    感觉像是没用 pandas ,而是自己解析和处理 csv 。对于 pandas 来说 3GB 的文件不大。
    NoOneNoBody
        4
    NoOneNoBody  
       177 天前
    你这个需要汇总么?不需要的话,读一行处理一行,添加到相应文件
    如果只是拆分,不需要计算的话,按这种方式纯文字处理很快的
    SuperXX
        5
    SuperXX  
       177 天前 via iPhone
    拆分的闭着眼睛用 np.split
    读写慢 用 parquet 或者 DuckDB , 其实这个数据量才 3GB….

    楼主得好好提升一下自己的语文, 虽然不知道你到底要表达啥,我还是盲猜吧
    ho121
        6
    ho121  
       177 天前 via Android
    不如试试 Access
    bianhui
        7
    bianhui  
       177 天前
    没看明白啥意思,如果导出 xlsx excel 直接另存为不就行了吗。如果解析数据,read line ,不要 read lines 。
    hyperbin
        8
    hyperbin  
       177 天前 via Android
    excel 最多 1048576 行
    missuo
        9
    missuo  
       177 天前 via iPhone
    用 readline ,不要用 readlines ,不就行了
    jiminjohn0402
        10
    jiminjohn0402  
    OP
       177 天前
    @l1xnan 确实说的有问题,是因为两个原因要拆分
    1 、文件太大,单独打开太慢
    2 、即便打开了提示字段超长,可能现实不全,但是转为 xlsx 不会有这个问题
    然后就开始想拆分方案,我自己参考网上的方案写了一份,感觉有点慢:

    import pandas as pd

    # 读取 CSV 文件
    data = pd.read_csv('customer.csv')

    # 按照“客户编号”列排序
    # 转换为字符串列排序
    data['客户编号'] = data['客户编号'].astype('str')
    sorted_data = data.sort_values(by='客户编号', ascending=False)

    # 将数据拆分为 30 个数据桢并保存为 CSV 文件
    num_files = 30
    chunk_size = len(sorted_data) // num_files

    for i in range(num_files):
    start_idx = i * chunk_size
    if i < num_files - 1:
    end_idx = (i + 1) * chunk_size
    else:
    end_idx = len(sorted_data)

    chunk = sorted_data.iloc[start_idx:end_idx]
    chunk.to_excel(f'chunk_{i + 1}.xlsx', index=False)
    laqow
        11
    laqow  
       177 天前
    直接 bash 下用 head -l 拆不就行了?拆完每个文件加上第一个文件的第一行,然后用 python 或什么别的多进程转成 excel 。
    超过 10M 的文件都不要用 excel ,不然每次打开都要等半天,excel 还有各种自动转码的 feature ,长数字转 int 超长截断,反斜杠变日期之类的。reCSVEditor 之类的直接看 csv 要简单很多。
    Maerd
        12
    Maerd  
       177 天前
    xlsx 自带压缩,基础数据类型也和 csv 不同,你在转出时首先要将数据格式转成 xlsx 的格式,然后再进行压缩,你想想这能快吗
    jiyan5
        13
    jiyan5  
       177 天前
    吐槽下 excel 的后缀名是啥玩意,不如 doc ppt 的好记
    volvo007
        14
    volvo007  
       177 天前
    @jiminjohn0402 有点慢是多慢?一般最新的 pandas 打开 3G 的 csv 应该和玩一样。如果慢,可能和你的数据类型有关,比如如果日期类比较多的话,pd 会用不同的日期格式去匹配,这个过程也是非常慢的。嫌慢也可以考虑基于 pyarrow 的 polars 去处理。arrow 是 Apache 的顶级框架之一,专门用来处理大数据的。此外,pd 是基于 numpy 的,而 numpy 本身不包含 string 类型,因为这不是 numpy 最关心的问题,它都是“数据”计算。所以如果文本类型比较多得话,还是考虑 pyarrow 这种原生支持 string 的库去处理才是合适的
    djangovcps
        15
    djangovcps  
       177 天前
    众所周知 python 的各种库 写 excel 都是慢的,根本就没说到点子上,真的嫌慢,用 python3.11 有伪 jit 加速,写 xlsx 会快 80%,我试过的
    jiminjohn0402
        16
    jiminjohn0402  
    OP
       177 天前 via iPhone
    @volvo007 大概花了两个小时分拆出 30 个文件,每个文件 80 多万条数据
    NoOneNoBody
        17
    NoOneNoBody  
       177 天前
    @jiminjohn0402 #10
    首先看你写的,并不需要 pandas ,逐条读取,提取客户编号作为判断,然后写到 xlsx ,加几个计数器的事,当然这样没有排序,但可以不同客户编号用不同输出

    或者倒入 sqlite ,后面就不用说了

    然后说这段代码
    1.sort_values 应该加上 ignore_index=True ,重排 index
    2.你这个完全可以用 groupby ,不用 sort ,2000w 条为了分编号 sort 没必要
    3.有个 more_itertools.chunked ,不用自己算切片
    4.也可以用 while + dataframe.head ,每次 drop 已完成的部分

    看整个流程关键点是排序,而且你这个也仅仅是客户编号排序而已,如果这不是必须的,选择方式就很多了
    volvo007
        18
    volvo007  
       177 天前
    @jiminjohn0402 这个速度非常不正常,可能的话再多给一些数据结构的信息吧,或者直接上代码,做个列名的脱敏处理。30 个文件,每个才 100 M ,这种估计 2-5 分钟完成比较正常
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2673 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 11:11 · PVG 19:11 · LAX 04:11 · JFK 07:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.