为2D阵列实现numpy in1d?

时间:2013-04-25 09:09:36

标签: python numpy

我有一个2D numpy数组S代表一个状态空间,有80000000行(作为状态)和5列(作为状态变量)。

我用S初始化K0,并且在每次迭代中,我对Ki中的所有状态应用状态转移函数f(x),并删除其f(x)不在Ki中的状态,从而得到Ki + 1。直到它收敛,即Ki + 1 = Ki。

这样做需要很长时间:

K = S
to_delete = [0]
While to_delete:
    to_delete = []
    for i in xrange(len(K)):
        if not f(i) in K:
        to_delete.append(K(i))
    K = delete(K,to_delete,0)

所以我想制作一个矢量化实现:

在列中切片K,应用f并再次连接它们,从而以某种方式获得f(K)。

现在的问题是如何获得一个长度为len(K)的数组,比如Sel,其中每一行Sel [i]确定f(K [i])是否在K中。正如in1d函数一样。< / p>

然后制作

会很简单
K=K[Sel]]

3 个答案:

答案 0 :(得分:4)

您的问题很难理解,因为它包含无关的信息并且包含拼写错误。如果我理解正确,您只需要一种有效的方法对2D数组的行执行设置操作(在这种情况下是Kf(K)行的交集。)

如果您创建numpy.in1d视图,则可以使用structured array执行此操作。

代码:

如果是K

In [50]: k
Out[50]:
array([[6, 6],
       [3, 7],
       [7, 5],
       [7, 3],
       [1, 3],
       [1, 5],
       [7, 6],
       [3, 8],
       [6, 1],
       [6, 0]])

这是f(K)(对于这个例子,我从第一个col中减去1并将第1个减去1):

In [51]: k2
Out[51]:
array([[5, 7],
       [2, 8],
       [6, 6],
       [6, 4],
       [0, 4],
       [0, 6],
       [6, 7],
       [2, 9],
       [5, 2],
       [5, 1]])

然后您可以通过执行以下操作找到Kf(K)中的所有行:

In [55]: k[np.in1d(k.view(dtype='i,i').reshape(k.shape[0]),k2.view(dtype='i,i').
reshape(k2.shape[0]))]
Out[55]: array([[6, 6]])

viewreshape创建平面结构化视图,以便每行显示为in1d的单个元素。 in1d创建匹配项的k的布尔索引,用于表示索引k并返回已过滤的数组。

答案 1 :(得分:0)

以上答案很棒。

但是,如果一个人不想与结构化阵列混在一起,并希望一个不关心数组类型的解决方案,也不需要关注数组元素的维度我想出了这个:

k[np.in1d(list(map(np.ndarray.dumps, k)), list(map(np.ndarray.dumps, k2)))]

基本上是list(map(np.ndarray.dumps, k))而不是k.view(dtype='f8,f8').reshape(k.shape[0])

考虑到这个解决方案慢了约50倍。

k = np.array([[6.5, 6.5],
       [3.5, 7.5],
       [7.5, 5.5],
       [7.5, 3.5],
       [1.5, 3.5],
       [1.5, 5.5],
       [7.5, 6.5],
       [3.5, 8.5],
       [6.5, 1.5],
       [6.5, 0.5]])
k = np.tile(k, (1000, 1))

k2 = np.c_[k[:, 0] - 1, k[:, 1] + 1]


In [132]: k.shape, k2.shape
Out[132]: ((10000, 2), (10000, 2))

In [133]: timeit k[np.in1d(k.view(dtype='f8,f8').reshape(k.shape[0]),k2.view(dtype='f8,f8').reshape(k2.shape[0]))]
10 loops, best of 3: 22.2 ms per loop

In [134]: timeit k[np.in1d(list(map(np.ndarray.dumps, k)), list(map(np.ndarray.dumps, k2)))]
1 loop, best of 3: 892 ms per loop

小输入可能是微不足道的,但对于操作,它需要1小时20分钟而不是2分钟。

答案 2 :(得分:0)

不确定我是否完全理解你的问题,但是如果Paul的解释是正确的,那么可以使用numpy_indexed包有效地解决它并完全向量化,如下所示:

import numpy_indexed as npi
K = npi.intersection(K, f(K))

此外,这适用于任何类型或形状的行。