<h2>简短回答</h2>
<p>请看最后快速但复杂的函数。在</p>
<h2>发展</h2>
<p>对<code>trace</code>进行迭代是很好的,但我不确定它是否比pandas解决方案更好。这两种方法都涉及对角线或列上的迭代。从概念上讲,它更简单或更干净,但我不确定速度,尤其是在大型阵列上。在</p>
<p>每条对角线有不同的长度,<code>[[12],[9,13],...]</code>。这是一个巨大的危险信号,警告我们块数组操作即使不是不可能的话也是困难的。在</p>
<p>使用<code>scipy.sparse</code>我可以构造一个二维数组,该数组可以求和得到这些轨迹:</p>
<pre><code>In [295]: from scipy import sparse
In [296]: xs=sparse.dia_matrix(x)
In [297]: xs.data
Out[297]:
array([[12, 0, 0],
[ 9, 13, 0],
[ 6, 10, 14],
[ 3, 7, 11],
[ 0, 4, 8],
[ 0, 1, 5],
[ 0, 0, 2]])
In [298]: np.sum(xs.data,axis=1)
Out[298]: array([12, 22, 30, 21, 12, 6, 2])
</code></pre>
<p>这种稀疏格式将其<code>data</code>存储在2d数组中,并进行必要的移位。事实上,你的<code>pd.concat</code>产生了类似的结果:</p>
^{pr2}$
<p>看起来<code>sparse</code>创建了这个<code>data</code>数组,方法是从<code>np.zeros</code>开始,并用适当的索引填充它:</p>
<pre><code> data[row_indices, col_indices] = x.ravel()
</code></pre>
<p>比如:</p>
<pre><code>In [344]: i=[4,5,6,3,4,5,2,3,4,1,2,3,0,1,2]
In [345]: j=[0,1,2,0,1,2,0,1,2,0,1,2,0,1,2]
In [346]: z=np.zeros((7,3),int)
In [347]: z[i,j]=x.ravel()[:len(i)]
In [348]: z
Out[348]:
array([[12, 0, 0],
[ 9, 13, 0],
[ 6, 10, 14],
[ 3, 7, 11],
[ 0, 4, 8],
[ 0, 1, 5],
[ 0, 0, 2]])
</code></pre>
<p>尽管我仍然需要一种为任何形状创建<code>i,j</code>的方法。对于<code>j</code>来说,这很简单:</p>
<pre><code>j=np.tile(np.arange(3),5)
j=np.tile(np.arange(x.shape[1]),x.shape[0])
</code></pre>
<p>重塑<code>i</code></p>
<pre><code>In [363]: np.array(i).reshape(-1,3)
Out[363]:
array([[4, 5, 6],
[3, 4, 5],
[2, 3, 4],
[1, 2, 3],
[0, 1, 2]])
</code></pre>
<p>让我用以下方法重现:</p>
<pre><code>In [371]: ii=(np.arange(3)+np.arange(5)[::-1,None]).ravel()
In [372]: ii
Out[372]: array([4, 5, 6, 3, 4, 5, 2, 3, 4, 1, 2, 3, 0, 1, 2])
</code></pre>
<p>所以一起:</p>
<pre><code>def all_traces(x):
jj = np.tile(np.arange(x.shape[1]),x.shape[0])
ii = (np.arange(x.shape[1])+np.arange(x.shape[0])[::-1,None]).ravel()
z = np.zeros(((x.shape[0]+x.shape[1]-1),x.shape[1]),int)
z[ii,jj] = x.ravel()
return z.sum(axis=1)
</code></pre>
<p>它需要对各种形状进行更多的测试。在</p>
<p>此函数比跟踪上的迭代更快,即使使用这个小尺寸的数组:</p>
<pre><code>In [387]: timeit all_traces(x)
10000 loops, best of 3: 70.5 µs per loop
In [388]: timeit [np.trace(x,i) for i in range(-(x.shape[0]-1),x.shape[1])]
10000 loops, best of 3: 106 µs per loop
</code></pre>