首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
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
Coding
V2EX  ›  Python

pandas 处理数据慢,求好方法

  •  
  •   zky001 · 123 天前 · 2066 次点击
    这是一个创建于 123 天前的主题,其中的信息可能已经有所发展或是发生改变。

    各位大佬,我有一个文本,里面有 54 万行数据,其中一列数据是类似 1234,2345,3122,3442 这样的一个字符串,我要把这列数据分割成四列数据,用 split 分割着四列在加一个 pandas dataframe 实现,每次跑半个多小时到一个多小时程序就 down 掉了,有啥好的思路方法完成这样的需求吗?

    30 回复  |  直到 2019-08-15 18:12:55 +08:00
        1
    zky001   123 天前
    想过把这些数据导入数据库处理,但是类似 1234,2345,3122,3442 的数据找不到一个好的对应的数据格式
        2
    liprais   123 天前 via iPhone
    spark 处理完了写进数据库
        3
    Vanderick   123 天前
    read 的时候用 chunksize,此时 df 本质是生成器,然后去迭代读;另外 pandas 有 str.split()内置方法
        4
    ipwx   123 天前
    遇事不决,上 C++。
    ----

    讲道理你这 54 万行而已,Python for line 都能解决,为啥一定要 pandas dataframe。
        5
    zky001   123 天前
    @ipwx 主要是时间太长了,c++时间也没减下来
        6
    ipwx   123 天前
    @zky001 这样的话我觉得你程序哪里肯定写的不太好。

    首先一点可以明确的就是,别的任何其他方案能做到的,C++ 一定也能做到。
    ----

    54 万行真的不多,C++ 的话不要用 iostream/fstream,用 fopen/fscanf 甚至是 open/read 然后手工解析。

    肯定能优化好的。
        7
    Darcy90   123 天前
    可以试试 dask,话说 54 万行用 apply 不至于这么慢吧
        8
    upczww   123 天前
    Python for 循环绝对要不了那么久,碰巧我刚才处理了一个 200 多万行的文本文件,为什么一分钟不到就处理完了。
        9
    joson1205   123 天前
    肯定是代码算法逻辑有问题,不可能那么久
        10
    dongxiao   123 天前
    import pandas as pd
    data = pd.DataFrame(["1234, 2341, 3412, 3123"]*10, columns=["just_a_column"])
    ret = data.just_a_column.str.split(", ", expand=True)
        11
    Jafee   123 天前 via iPhone
    54 万行不多,跑那么久不太应该,可以看看优化一下代码。
        12
    arrow8899   123 天前
    一行大概多长啊? 再发下代码吧。我本地生成了 100W 行数据,split 然后写入另外一个文件,10 秒钟就完事
        13
    bugcoder   123 天前
    pandas 0.25 的 explode 了解一下
        14
    upczww   123 天前
    楼主可以发一行数据出来看看
        15
    qianc1990   123 天前
    pd.read_csv('file_name', sep=','), 这样不就可以了吗...
        16
    hjq98765   123 天前
    放代码上来,我猜是你不断地 df.append(df)了,pandas 每次生成一个新 df 都会巨慢无比,但是 54w 行也就算个毛毛雨
        17
    zilaijuan   123 天前 via Android
    dataframe 的 map 方法,试一下
        18
    MMMMMMMMMMMMMMMM   123 天前
    用 gpu 跑

    N 卡有 cuda,A 卡不太清楚
        19
    lulu00147   123 天前 via iPhone
    Emeditor 正则表达式 了解一下
        20
    AX5N   123 天前
    肯定是你的程序逻辑有问题,你是不是实际上遍历了 54w*54w 次...
        21
    zky001   122 天前
    @AX5N 实际遍历了 54 万次,但是对每一行都要进行一次裁剪拼加 dataframe 的操作,就很耗时
        22
    zky001   122 天前
    @qianc1990 这个数据中列向量还有中文,中文中也有各种逗号,pd 直接读进来会把中文中的逗号也切片进来占用其他数据列
        23
    rouwanzi   122 天前
    不要一行行拼,对一列统一操作的时候,可以用 map 或者 pandas 的 apply 这种方法,很久没写过 pandas 的了,具体的细节有点忘记,每行都这样操作 df 肯定慢
        24
    zky001   122 天前
    @dongxiao 这个是建立了一个新 dataframe,出来的是裁剪处理后的,可以直接 concat 到原 dataframe 上吗,还要到另一个几十万行的文件中把"1234, 2341, 3412, 3123"这些转换成对应中文
        25
    zky001   122 天前
    一列数据是类似 1234,2345,3122,3442 这样的一个字符串,我要把这列数据分割成四列数据,分完后再进另一个去查找,之前写的逻辑代码类似如下:
    for u in range(0,products.shape[0]):
    start=time.time()
    cat1=products.catIds[u].split(',')[0]
    #print(categories[categories['catId']==int(cat1)].index[0])
    category1=categories['category'][categories[categories['catId']==int(cat1)].index[0]]
    cat2=products.catIds[u].split(',')[1]
    category2=categories['category'][categories[categories['catId']==int(cat2)].index[0]]
    cat3=products.catIds[u].split(',')[-1]
    category3=categories['category'][categories[categories['catId']==int(cat3)].index[0]]
    df=df.append({"catIds":products.catIds[u],"cat1":category1,"cat2":category2,"cat3":category3})
    end=time.time()
    print(end-start)
    ndf = pd.merge(products,df,how='left',on='catIds'),
        26
    rouwanzi   122 天前
    @zky001 大概是这个样子吧,很久没写了
    ```python
    import pandas as pd
    from pandas import DataFrame as df

    categories = {1:'aa', 2:'bb', 3:'cc', 4:'dd', 5:'ee'}
    data = df({'catIds':['1,2,3','2,3,4','3,4,5']})

    def process_data(catIds):
    ids = catIds.split(',')
    cats = [categories.get(int(catId), None) for catId in ids]
    return cats

    cats = list(map(process_data, data['catIds']))
    data[['cat1','cat2','cat3']] = df(cats, index=data.index)
    ```
        27
    cigarzh   122 天前
    Series.apply 啊,现在程序员都不看文档的吗……
        28
    yeyu1989   122 天前
    @cigarzh 正解
        29
    lmingzhi08   122 天前
    54 万行不算很多...
    obj = df['target_col']
    objn = obj.str.split(',')
    for i in range(4):
    df['col_%s' % i] = objn.str[i]

    如果再觉得内存不够,分批次处理,每次处理个 1 万行,使用 chunksize
    https://blog.csdn.net/zm714981790/article/details/51375475
    df_list = pd.read_table('tmp.sv', sep='|', chunksize=4)
    for df in df_list:
    print(chunk)

    如果想要再加速,那么试试多进程,每次后存成一个单独的文件,最后再合并,应该几分钟搞定
        30
    Baboonowen   122 天前
    Series.apply 是真的正解
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   919 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 35ms · UTC 18:57 · PVG 02:57 · LAX 10:57 · JFK 13:57
    ♥ Do have faith in what you're doing.