np.fromfunction:引用其他数组

时间:2016-05-29 14:20:30

标签: python arrays numpy

我正在尝试根据一个数组中的值是否在另一个数组中来创建数组。我希望以下内容能够奏效:

A = np.fromfunction(lambda x, y: tuple(order[x,:]) in paths[y,],\
    shape=((len(order), len(paths))), dtype=int)

不幸的是,这只会产生一个标量值而不是我想要的数组。我可以通过如下的for循环实现相同的目的,但由于涉及的值的数量,此选项非常慢。

A = np.zeros(shape=(len(order), len(paths)), dtype=int)
for i in np.ndindex(len(order), len(paths)):
    r = i[0] # Row
    c = i[1] # Column
    x = r + c + (len(paths)-1)*r
    if paths[c,] == None:
        pass
    elif tuple(order[r,:]) in paths[c,]:
        np.put(A, x, 1, 'wrap')

有没有人有一种有效的方法来生成目标矩阵?非常感谢你的帮助!

\ edit:非常感谢你的提示hpaulj。我认为np.where进入了我想要实现的目标,但无法处理两个数组的复杂性。我编辑了上面的方法,因为x = r*c if r*c != 0 else r+c没有给我我想要的结果 - 当我的输出是胡言乱语时,我以某种方式想出来...... x = r + c + (len(paths)-1)*r但是确实能够唯一地识别每个位置平坦的2D阵列。我在下面提供的样本应该让我更清楚我想要实现的目标。抱歉混乱!

order
[[ 73   6   3   1]
 [ 73   6   3   2]
 [  6 116   3   1]
 [  6 116   3   2]
 [116  45   3   1]
 ...10k additional lines...]

paths
[ [(12, 14, 1615, 1), (14, 156, 1615, 1), (156, 83, 1615, 1), (83, 37, 1554, 1), (37, 36, 1554, 1)]
  [(12, 14, 1615, 2), (14, 156, 1615, 2), (156, 83, 1615, 2), (83, 37, 1554, 2), (37, 36, 1554, 2)]
  [(12, 14, 1615, 1), (14, 156, 1615, 1), (156, 83, 1615, 1), (83, 37, 1554, 1), (37, 36, 1554, 1)]
  [(12, 14, 1615, 2), (14, 156, 1615, 2), (156, 83, 1615, 2), (83, 37, 1554, 2), (37, 36, 1554, 2)]
  [(12, 14, 1615, 1), (14, 156, 1615, 1), (156, 83, 1615, 1), (83, 37, 1554, 1), (37, 36, 1554, 1)]
  [(12, 14, 1615, 2), (14, 156, 1615, 2), (156, 83, 1615, 2), (83, 37, 1554, 2), (37, 36, 1554, 2)]
  ...600 additional lines...]

目标是检查order的每个值是否在paths范围内,并且在行/列交叉点中放置True1。所有其他交叉点应为False / 0。维持行和列的顺序是至关重要的,因为矩阵然后乘以有序向量。实际上我正在研究这个(URL - 见下文,p94)算法。该矩阵应该反映特定产品(order)对特定资源(paths)的利用率。

网址:https://books.google.com/books?id=GhdDbEM-_5oC&lpg=PA100&ots=wH5OVDz7JV&dq=dlp%20revenue%20management&pg=PA94#v=onepage&q&f=false

1 个答案:

答案 0 :(得分:2)

查看代码表单fromfunction

args = indices(shape, dtype=dtype)
return function(*args,**kwargs)

np.indicesmeshgrid

类似
In [28]: np.indices((2,3))
Out[28]: 
array([[[0, 0, 0],
        [1, 1, 1]],

       [[0, 1, 2],
        [0, 1, 2]]])

所以np.fromfunction(lambda i, j: i + j, (3, 3), dtype=int)相当于做

In [29]: idn=np.indices((2,3))
In [31]: idn[0]+idn[1]
Out[31]: 
array([[0, 1, 2],
       [1, 2, 3]])

我通常使用广播:np.arange(2)[:,None] + np.arange(3)

有一个np.frompyfunc将Python函数应用于其输入的每个元素。但它只适用于1d(虽然结构化数组周围有一些巧妙的技巧)。 np.vectorize也使用此功能。但两者仍在迭代,因此节省的时间最多为2倍。

===============

ndindex是另一种生成索引值的方法

In [42]: list(np.ndindex(2,3))
Out[42]: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]

In [43]: list(zip(*np.ndindex(2,3)))
Out[43]: [(0, 0, 0, 1, 1, 1), (0, 1, 2, 0, 1, 2)]

使用zip转置,我得到的值类似于nd.indices生成的值(但是已经过了)。

======================

如果没有orderpaths的示例值,很难想象您的功能正在做什么。或者更确切地说,只是通过阅读代码我无法描绘它正在做什么,没有样本我就无法进行测试。对于' blackbox'采用标量i,j坐标的函数,你的方法就像它得到的一样好。为了使它快速,你必须重做函数,以便它使用直接使用np.indices的子数组,而不是迭代。

===============

获取x值的矢量化方法可能是

In [105]: I,J=np.indices((3,3))

In [106]: np.where(I*J,I*J,I+J)
Out[106]: 
array([[0, 1, 2],
       [1, 1, 2],
       [2, 2, 4]])

where在整个数组上执行x = r*c if r*c != 0 else r+c

布尔掩码(数组if测试的一个好工具)的相同之处是:

In [114]: x=I*J

In [115]: mask = x==0

In [116]: x[mask]=(I+J)[mask]

In [117]: x
Out[117]: 
array([[0, 1, 2],
       [1, 1, 2],
       [2, 2, 4]])