关于python:如何将深度为2的元组转换为2D Numpy数组?

How to convert a tuple of depth 2 to a 2D Numpy array?

下面的代码不会生成我想要的;将一个元组中的每个元组转换为一个numpy数组,因此给了我使用多个索引检索值的选项。

1
2
3
import numpy as np
a=np.asarray([[1,2,3],[2,3,4,5]])
print a

输出是错误:

1
IndexError: too many indices

但是我希望它检索的是1,因为第一个元组第一个元组第一个值是1。我该如何使这种转变发生呢?

更新:有趣的是,当我尝试以下方法时:

1
2
3
a=np.asarray([np.asarray([1,2,3]),np.asarray([2,3,4,5])])
b=np.asarray([np.asarray([1,2,3]),np.asarray([2,3,4,5])])
print np.multiply(a,b)

产生所需的输出!它是一个元素一个元素的乘法。

1
[array([1, 4, 9]) array([ 4,  9, 16, 25])]


由于长度不同,无法将示例直接转换为numpy数组。您得到的结果是一个1d numpy数组,其中包含python列表对象。我已经看到了您所要做的,称之为锯齿状数组,但不确定这是否是任何形式的官方术语。

您可以用零填充元素,或者使用稀疏矩阵,或者不转换为numpy。取决于你的总体目标。

下面介绍如何从交错数组中设置一个蒙面数组并沿轴计算和。如果有人比我更喜欢使用这个模块,他可能会提出更有效或更惯用的建议:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
>>> a = np.array([[[1,2,3],[2,3,4,5], [2, 2]],[[3,4,5,6,7],[1],[2,3,10]]])
>>> D = max(len(x) for x in y for y in a)
>>> padded = [[x + [0] * (D-len(x)) for x in y] for y in a]
>>> mask = [[[0] * len(x) + [1] * (D-len(x)) for x in y] for y in a]
>>> result = np.ma.masked_array(padded, np.array(mask, dtype=np.bool))
>>> result
masked_array(data =
 [[[1 2 3 -- --]
  [2 3 4 5 --]
  [2 2 -- -- --]]

 [[3 4 5 6 7]
  [1 -- -- -- --]
  [2 3 10 -- --]]],
             mask =
 [[[False False False  True  True]
  [False False False False  True]
  [False False  True  True  True]]

 [[False False False False False]
  [False  True  True  True  True]
  [False False False  True  True]]],
       fill_value = 999999)

>>> np.sum(result, axis=-1)
masked_array(data =
 [[6 14 4]
 [25 1 15]],
             mask =
 [[False False False]
 [False False False]],
       fill_value = 999999)

>>>


如果我更改了你的ab,那么numpy会生成一个二维数组,而不是数组:

1
2
3
4
In [5]: am=np.asarray([np.asarray([1,2,3,0]),np.asarray([2,3,4,5])])
#array([[1, 2, 3, 0],
#       [2, 3, 4, 5]])
In [7]: bm=np.asarray([np.asarray([1,2,3,0]),np.asarray([2,3,4,5])])

做计时:

1
2
3
4
5
In [10]: timeit np.multiply(a,b)
100000 loops, best of 3: 7.94 us per loop

In [11]: timeit np.multiply(am,bm)
100000 loops, best of 3: 1.89 us per loop

纯ndarray乘法实质上更快。在一种情况下,它可以直接跳到一个接一个的元素乘法中(在快速的C代码级别);在另一种情况下,它执行通用的迭代,使用对象而不是简单的数字。它正在做一些接近于用Python迭代的事情。

事实上,如果我显式地做那个循环,我会得到接近那个更长时间的东西。

1
2
3
al,bl=a.tolist(), b.tolist()
In [21]: timeit np.array([np.multiply(x,y) for x,y in zip(al,bl)])
100000 loops, best of 3: 8.99 us per loop

现在让我们来看看你的"最后一个维度的总和"问题。首先要注意,sumadd.reduce没有被扩展到使用这种类型的数组。

1
2
3
4
5
In [37]: timeit am.sum(axis=1)
100000 loops, best of 3: 11.5 us per loop

In [38]: timeit [x.sum() for x in a]
10000 loops, best of 3: 21.5 us per loop

ndarray sum的速度优势没有那么大。sum可以通过编码为dot产品(带np.doteinsum来加速:

1
2
3
4
5
6
7
8
9
10
11
12
13
In [42]: timeit np.einsum('ij->i',am)
100000 loops, best of 3: 4.79 us per loop

In [50]: ones=np.array([1,1,1,1])
In [51]: timeit np.dot(am,ones)
100000 loops, best of 3: 2.37 us per loop

In [55]: timeit [np.einsum('j->',x) for x in a]
100000 loops, best of 3: 12.3 us per loop

In [64]: c=np.asarray([np.asarray([1,1,1]),np.asarray([1,1,1,1])])  
In [65]: timeit [np.dot(x,y) for x,y in zip(a,c)]
100000 loops, best of 3: 8.12 us per loop

因此,尽管可以构造不规则数组(或数组数组),但它们没有比数组列表更大的速度优势。快速的numpy数组操作通常不与通用的python对象(dtype=object元素)一起工作。