【问题标题】:Mapping diagonal映射对角线
【发布时间】:2020-02-24 22:33:08
【问题描述】:

假设我有以下数据框:

idx = ['H',"A","B","C","D"]
idxp = idx[1:] + [idx[0]]
idxm = [idx[-1]] + idx[:-1]
idx, idxp, idxm
j = np.arange(25).reshape(5,5)
J = pd.DataFrame(j, index=idx, columns=idx)
np.fill_diagonal(J.values, 0)
J

作为输出,我想得到这样的数组:

  • 我们在矩阵的下部和对角线处处处都是零
  • 在矩阵的上部具有值,通过取矩阵 J 对角线上方的数字计算得出,因此向量 v = [1, 7, 13, 19]。
  • 使用 v,计算第一行作为 v 的累积和 从头到尾得到[1,8,21,40]
  • 使用v,计算第二行v从第二个索引到末尾的累积和,得到[7,20,39]
  • 以此类推,直到到达 v 的最后一个索引

换句话说,这会给我们下面的矩阵:

m_exp = np.array([[0,1,8,21,40],
             [0,0,7,20,39],
             [0,0,0,13,32],
             [0,0,0,0,19],
             [0,0,0,0,0],
             ])

到目前为止,我发现计算此矩阵的最佳方法是使用以下代码:

travelup = np.array([np.pad(np.cumsum(J.values.diagonal(1)[n:]), (n+1,0), 'constant') for n in range(J.values.shape[0])])

然而,这涉及一个理解列表,实际上我的矩阵要大得多,这段代码被调用了数千次。

有没有什么方法可以通过使用映射来转换流程以使其更快地避免循环?

【问题讨论】:

    标签: python pandas performance numpy vectorization


    【解决方案1】:

    列出的方法很少。

    我。基本方法

    a = J.values
    p = np.r_[0,a.ravel()[1::a.shape[1]+1]] # or np.r_[0,np.diag(a,1)]
    n = len(p)
    out = np.triu(np.broadcast_to(p,(n,n)),1).cumsum(1)
    

    pn 将在下面列出的替代方案中重复使用。

    A.备选方案#1

    或者使用broadcasted-multiplication 来获得最终输出 -

    out = (~np.tri(n, dtype=bool)*p).cumsum(1)
    

    B.备选方案#2

    或者在 cumsum 上使用outer-subtraction -

    c = p.cumsum()
    out = np.triu(c-c[:,None])
    

    C.备选方案#3

    或者用np.tri替换np.triu -

    out = (c-c[:,None])*~np.tri(n, dtype=bool)
    

    c 将在接下来列出的替代方案中重复使用。

    二。与numexpr

    对于大型阵列,使用numexpr 来利用多核。因此,替代方案将是 -

    import numexpr as ne
    
    out = ne.evaluate('(c-c2D)*M',{'c2D':c[:,None],'M':~np.tri(n, dtype=bool)})
    

    A.备选方案#1

    out = ne.evaluate('(c-c2D)*(~M)',{'c2D':c[:,None],'M':np.tri(n, dtype=bool)})
    

    B.备选方案#2

    r = np.arange(n)
    out = ne.evaluate('(c-c2D)*(r2D<r)',{'c2D':c[:,None],'r2D':r[:,None]})
    

    【讨论】:

      猜你喜欢
      • 2021-10-31
      • 2014-12-11
      • 2021-08-02
      • 1970-01-01
      • 2018-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-30
      相关资源
      最近更新 更多