映射对角线
Mapping diagonal
假设我有以下数据框:
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])])
但是这涉及到一个理解列表,实际上我的矩阵要大得多,这段代码被调用了数千次。
有没有什么方法可以通过使用映射来转换流程,使其更快地避免循环?
列出的方法很少。
我。基本方法
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)
p
和 n
将在接下来列出的备选方案中重复使用。
一个。备选 #1
或者用broadcasted-multiplication
得到最终输出-
out = (~np.tri(n, dtype=bool)*p).cumsum(1)
乙。备选 #2
或者在 cumsum 上使用 outer-subtraction
-
c = p.cumsum()
out = np.triu(c-c[:,None])
摄氏度。备选 #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)})
一个。备选 #1
out = ne.evaluate('(c-c2D)*(~M)',{'c2D':c[:,None],'M':np.tri(n, dtype=bool)})
乙。备选 #2
r = np.arange(n)
out = ne.evaluate('(c-c2D)*(r2D<r)',{'c2D':c[:,None],'r2D':r[:,None]})
假设我有以下数据框:
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])])
但是这涉及到一个理解列表,实际上我的矩阵要大得多,这段代码被调用了数千次。
有没有什么方法可以通过使用映射来转换流程,使其更快地避免循环?
列出的方法很少。
我。基本方法
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)
p
和 n
将在接下来列出的备选方案中重复使用。
一个。备选 #1
或者用broadcasted-multiplication
得到最终输出-
out = (~np.tri(n, dtype=bool)*p).cumsum(1)
乙。备选 #2
或者在 cumsum 上使用 outer-subtraction
-
c = p.cumsum()
out = np.triu(c-c[:,None])
摄氏度。备选 #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)})
一个。备选 #1
out = ne.evaluate('(c-c2D)*(~M)',{'c2D':c[:,None],'M':np.tri(n, dtype=bool)})
乙。备选 #2
r = np.arange(n)
out = ne.evaluate('(c-c2D)*(r2D<r)',{'c2D':c[:,None],'r2D':r[:,None]})