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

python 如何优化双重循环?

  •  1
     
  •   billgreen1 · 2016-01-28 07:10:35 +08:00 · 4407 次点击
    这是一个创建于 3221 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有一个双重循环耗时比较多,主要可能在检查 index 上面:

    from scipy.stats import pearsonr
          # X,Y 是一个字典,每一个 key 对应一个序列 pandas.Series , 序列的元素是 float
          # 难点:序列的 index 可能不一致,比如 X[k1] 这个序列的 index 是 0 到 100 ,
          # Y[k2] 这个序列的 index 是 30 到 130 , X[k1] 和 Y[k2] 这两个序列里面可能有 nan 值。
          # 要求:取出 X[k1] 和 Y[k2] 这两个序列中索引相同的,且不含 nan 值的部分,做相关系数
          result = np.empty((len(X),len(y)))
          for kx in X.keys():
               for ky in Y.keys():
                    df = pd.DataFrame({'col1':X[kx], 'col2':Y[ky]}).dropna()  # 耗时几乎都在这上面了 
                    result[kx,ky] = pearsonr(df.col1, df.col2)
    

    真正的 pearsonr 并不耗费多少时间,请教该如何优化是好?

    6 条回复    2016-01-28 11:06:56 +08:00
    yelite
        1
    yelite  
       2016-01-28 07:20:45 +08:00
    试试看不创建 DataFrame ,用 is_nan 之类的函数生产两个 Bool Series ,然后 and 一下作为 index ,最后应该是 `pearsonr(X[kx][idx], Y[ky][idx])` 这种感觉
    fractal314
        2
    fractal314  
       2016-01-28 07:24:23 +08:00 via Android
    倒数第二行的计算量是 o(n*n)的。自己写的话,应该是 o(n)的
    billgreen1
        3
    billgreen1  
    OP
       2016-01-28 07:29:24 +08:00
    @yelite 嗯,我目前是这个思路,然后能想到的只有 multiprocessing 了
    @fractal314 自己写为什么会是 O(n)的?

    应该是对象的创建占用了太多时间
    asj
        4
    asj  
       2016-01-28 07:43:36 +08:00 via Android
    不是很确定理解清楚了你的问题
    如果只是要找到两个字典中的序列号的话
    各循环一次插入同一张 Hashtable ,以 series 为 key , value 为插入次数。之后遍历 Hashtable 取出 value 为 2 的条目。
    fractal314
        5
    fractal314  
       2016-01-28 07:50:31 +08:00 via Android
    @billgreen1 1 楼和 4 楼的方法都是 o(n)的吧
    ruoyu0088
        6
    ruoyu0088  
       2016-01-28 11:06:56 +08:00
    先把所有序列的 nan 都删除掉,然后再进入双重循环。循环里面用 align(join="inner")对齐两个序列,相关文档: http://pandas.pydata.org/pandas-docs/version/0.17.1/generated/pandas.Series.align.html

    这样不需要创建 DataFrame 对象,速度应该有所提升。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3377 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 04:45 · PVG 12:45 · LAX 20:45 · JFK 23:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.