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
zky001
V2EX  ›  Python

pandas 处理数据慢,求好方法

  •  
  •   zky001 ·
    zky001 · 2019-08-14 15:59:42 +08:00 · 5077 次点击
    这是一个创建于 1931 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    讲道理你这 54 万行而已,Python for line 都能解决,为啥一定要 pandas dataframe。
    zky001
        5
    zky001  
    OP
       2019-08-14 16:46:58 +08:00
    @ipwx 主要是时间太长了,c++时间也没减下来
    ipwx
        6
    ipwx  
       2019-08-14 16:50:01 +08:00
    @zky001 这样的话我觉得你程序哪里肯定写的不太好。

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

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

    肯定能优化好的。
    Darcy90
        7
    Darcy90  
       2019-08-14 16:50:15 +08:00
    可以试试 dask,话说 54 万行用 apply 不至于这么慢吧
    upczww
        8
    upczww  
       2019-08-14 16:57:51 +08:00
    Python for 循环绝对要不了那么久,碰巧我刚才处理了一个 200 多万行的文本文件,为什么一分钟不到就处理完了。
    joson1205
        9
    joson1205  
       2019-08-14 17:00:15 +08:00
    肯定是代码算法逻辑有问题,不可能那么久
    dongxiao
        10
    dongxiao  
       2019-08-14 17:00:20 +08:00
    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)
    Jafee
        11
    Jafee  
       2019-08-14 17:00:31 +08:00 via iPhone
    54 万行不多,跑那么久不太应该,可以看看优化一下代码。
    arrow8899
        12
    arrow8899  
       2019-08-14 17:01:14 +08:00
    一行大概多长啊? 再发下代码吧。我本地生成了 100W 行数据,split 然后写入另外一个文件,10 秒钟就完事
    bugcoder
        13
    bugcoder  
       2019-08-14 17:01:41 +08:00
    pandas 0.25 的 explode 了解一下
    upczww
        14
    upczww  
       2019-08-14 17:03:11 +08:00
    楼主可以发一行数据出来看看
    qianc1990
        15
    qianc1990  
       2019-08-14 17:07:13 +08:00
    pd.read_csv('file_name', sep=','), 这样不就可以了吗...
    hjq98765
        16
    hjq98765  
       2019-08-14 18:09:52 +08:00
    放代码上来,我猜是你不断地 df.append(df)了,pandas 每次生成一个新 df 都会巨慢无比,但是 54w 行也就算个毛毛雨
    zilaijuan
        17
    zilaijuan  
       2019-08-14 18:23:07 +08:00 via Android
    dataframe 的 map 方法,试一下
    MMMMMMMMMMMMMMMM
        18
    MMMMMMMMMMMMMMMM  
       2019-08-14 20:46:02 +08:00
    用 gpu 跑

    N 卡有 cuda,A 卡不太清楚
    lulu00147
        19
    lulu00147  
       2019-08-14 22:11:49 +08:00 via iPhone
    Emeditor 正则表达式 了解一下
    AX5N
        20
    AX5N  
       2019-08-15 00:26:14 +08:00
    肯定是你的程序逻辑有问题,你是不是实际上遍历了 54w*54w 次...
    zky001
        21
    zky001  
    OP
       2019-08-15 08:57:34 +08:00
    @AX5N 实际遍历了 54 万次,但是对每一行都要进行一次裁剪拼加 dataframe 的操作,就很耗时
    zky001
        22
    zky001  
    OP
       2019-08-15 09:01:55 +08:00
    @qianc1990 这个数据中列向量还有中文,中文中也有各种逗号,pd 直接读进来会把中文中的逗号也切片进来占用其他数据列
    rouwanzi
        23
    rouwanzi  
       2019-08-15 09:09:22 +08:00
    不要一行行拼,对一列统一操作的时候,可以用 map 或者 pandas 的 apply 这种方法,很久没写过 pandas 的了,具体的细节有点忘记,每行都这样操作 df 肯定慢
    zky001
        24
    zky001  
    OP
       2019-08-15 09:19:51 +08:00
    @dongxiao 这个是建立了一个新 dataframe,出来的是裁剪处理后的,可以直接 concat 到原 dataframe 上吗,还要到另一个几十万行的文件中把"1234, 2341, 3412, 3123"这些转换成对应中文
    zky001
        25
    zky001  
    OP
       2019-08-15 09:42:28 +08:00
    一列数据是类似 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'),
    rouwanzi
        26
    rouwanzi  
       2019-08-15 11:27:54 +08:00
    @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)
    ```
    cigarzh
        27
    cigarzh  
       2019-08-15 12:53:12 +08:00
    Series.apply 啊,现在程序员都不看文档的吗……
    yeyu1989
        28
    yeyu1989  
       2019-08-15 16:38:19 +08:00
    @cigarzh 正解
    lmingzhi08
        29
    lmingzhi08  
       2019-08-15 17:24:43 +08:00
    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)

    如果想要再加速,那么试试多进程,每次后存成一个单独的文件,最后再合并,应该几分钟搞定
    Baboonowen
        30
    Baboonowen  
       2019-08-15 18:12:55 +08:00
    Series.apply 是真的正解
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1029 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:43 · PVG 05:43 · LAX 13:43 · JFK 16:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.