Python 有效地重新调整Numpy阵列的形状/顺序,使其排列有序(图)

Python 有效地重新调整Numpy阵列的形状/顺序,使其排列有序(图),python,numpy,python-imaging-library,Python,Numpy,Python Imaging Library,我希望能够以某种方式重新排列numpy阵列,以便高效地处理瓷砖 我得到的是: >>> A = np.array([[1,2],[3,4]]).repeat(2,0).repeat(2,1) >>> A # image like array array([[[1, 1, 2, 2], [1, 1, 2, 2]], [[3, 3, 4, 4], [3, 3, 4, 4]]]) >>> A.res

我希望能够以某种方式重新排列numpy阵列,以便高效地处理瓷砖

我得到的是:

>>> A = np.array([[1,2],[3,4]]).repeat(2,0).repeat(2,1)
>>> A  # image like array
array([[[1, 1, 2, 2],
        [1, 1, 2, 2]],

       [[3, 3, 4, 4],
        [3, 3, 4, 4]]])

>>> A.reshape(2,2,4)
array([[[1, 1, 2, 2],
        [1, 1, 2, 2]],

       [[3, 3, 4, 4],
        [3, 3, 4, 4]]])
我想要的:如何获得X:

如果没有缓慢的python循环,这是可能的吗

奖励:从X转换回A

巴戈指出了我遗漏的一个类似问题:

为什么这么麻烦?能够做以下事情:

>>> X[X.sum(2)>12] -= 1
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [3, 3, 3, 3]]])
>>> X = A.reshape(2,2,2,2)
>>> X = X.transpose([0,2,1,3])
>>> X = X.reshape((2,2,-1))
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [4, 4, 4, 4]]])
>>> B = X.reshape((2,2,2,2))
>>> B = B.transpose([0,2,1,3])
>>> B = B.reshape((2,2,-1))
>>> B
array([[[1, 1, 2, 2],
        [1, 1, 2, 2]],

       [[3, 3, 4, 4],
        [3, 3, 4, 4]]])
编辑:解决方案:


我认为您只是看到了阵列的错误部分。以下内容应该是您想要的

>>> X[(X.sum(2)>12),:] -= 1
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [3, 3, 3, 3]]])
回到原来的顺序要复杂一点。我相信您可以将下面的代码修改为一个名为get_back的函数,这样您就不必一直重复使用它

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

# Make the change to the array
# Note that I make the change to +=1 so we can indeed see that
# the reshaping worked by looking for the 5's.
X[(X.sum(2)>12),:] += 1

(M,N,P) = X.shape;      # Number of tiles is MxN
orig_i = 2; orig_j = 2; # (Original rows/cols in a tile).
orig = (orig_i, orig_j) # Define as a tuple for convenience.
hstacks = []
for ii in range(M):
    hstacks.append(X[ii,0,:].reshape(orig))
    for jj in range(1,N):
        hstacks[-1] = np.hstack(( hstacks[-1], X[ii,jj,:].reshape(orig) ))

orig_array = hstacks[0]
for kk in range(1,len(hstacks)):
    orig_array = np.vstack(( orig_array, hstacks[kk] ))

# Print to confirm that it worked.
print orig_array
我得到以下信息:

>>> [[[1 1 1 1]
      [2 2 2 2]]

     [[3 3 3 3]
      [4 4 4 4]]]

>>> [[1 1 2 2]
     [1 1 2 2]
     [3 3 5 5]
     [3 3 5 5]]
为了测试,我尝试了一个更大的瓷砖图案,它给出了正确的结果。请注意,我使用了一个函数get_back来封装上述代码,我只是将平铺维度参数硬编码到函数中。实际上,它们应该是输入参数

>>> X = np.asarray([[[1,1,1,1],[2,2,2,2],[3,3,3,3]],
                    [[4,4,4,4],[5,5,5,5],[6,6,6,6]]])
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2],
        [3, 3, 3, 3]],

       [[4, 4, 4, 4],
        [5, 5, 5, 5],
        [6, 6, 6, 6]]])

>>> get_back(X)
array([[1 1 2 2 3 3]
       [1 1 2 2 3 3]
       [4 4 5 5 6 6]
       [4 4 5 5 6 6]])

我认为您只是看到了阵列的错误部分。以下内容应该是您想要的

>>> X[(X.sum(2)>12),:] -= 1
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [3, 3, 3, 3]]])
回到原来的顺序要复杂一点。我相信您可以将下面的代码修改为一个名为get_back的函数,这样您就不必一直重复使用它

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

# Make the change to the array
# Note that I make the change to +=1 so we can indeed see that
# the reshaping worked by looking for the 5's.
X[(X.sum(2)>12),:] += 1

(M,N,P) = X.shape;      # Number of tiles is MxN
orig_i = 2; orig_j = 2; # (Original rows/cols in a tile).
orig = (orig_i, orig_j) # Define as a tuple for convenience.
hstacks = []
for ii in range(M):
    hstacks.append(X[ii,0,:].reshape(orig))
    for jj in range(1,N):
        hstacks[-1] = np.hstack(( hstacks[-1], X[ii,jj,:].reshape(orig) ))

orig_array = hstacks[0]
for kk in range(1,len(hstacks)):
    orig_array = np.vstack(( orig_array, hstacks[kk] ))

# Print to confirm that it worked.
print orig_array
我得到以下信息:

>>> [[[1 1 1 1]
      [2 2 2 2]]

     [[3 3 3 3]
      [4 4 4 4]]]

>>> [[1 1 2 2]
     [1 1 2 2]
     [3 3 5 5]
     [3 3 5 5]]
为了测试,我尝试了一个更大的瓷砖图案,它给出了正确的结果。请注意,我使用了一个函数get_back来封装上述代码,我只是将平铺维度参数硬编码到函数中。实际上,它们应该是输入参数

>>> X = np.asarray([[[1,1,1,1],[2,2,2,2],[3,3,3,3]],
                    [[4,4,4,4],[5,5,5,5],[6,6,6,6]]])
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2],
        [3, 3, 3, 3]],

       [[4, 4, 4, 4],
        [5, 5, 5, 5],
        [6, 6, 6, 6]]])

>>> get_back(X)
array([[1 1 2 2 3 3]
       [1 1 2 2 3 3]
       [4 4 5 5 6 6]
       [4 4 5 5 6 6]])

您想要类似于:

>>> X[X.sum(2)>12] -= 1
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [3, 3, 3, 3]]])
>>> X = A.reshape(2,2,2,2)
>>> X = X.transpose([0,2,1,3])
>>> X = X.reshape((2,2,-1))
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [4, 4, 4, 4]]])
>>> B = X.reshape((2,2,2,2))
>>> B = B.transpose([0,2,1,3])
>>> B = B.reshape((2,2,-1))
>>> B
array([[[1, 1, 2, 2],
        [1, 1, 2, 2]],

       [[3, 3, 4, 4],
        [3, 3, 4, 4]]])

您想要类似于:

>>> X[X.sum(2)>12] -= 1
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [3, 3, 3, 3]]])
>>> X = A.reshape(2,2,2,2)
>>> X = X.transpose([0,2,1,3])
>>> X = X.reshape((2,2,-1))
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [4, 4, 4, 4]]])
>>> B = X.reshape((2,2,2,2))
>>> B = B.transpose([0,2,1,3])
>>> B = B.reshape((2,2,-1))
>>> B
array([[[1, 1, 2, 2],
        [1, 1, 2, 2]],

       [[3, 3, 4, 4],
        [3, 3, 4, 4]]])


你的问题是什么还不清楚。您列出的代码的哪一步不适合您。NumPy确实有逻辑类型索引,一些类似X[X.sum2>12]的东西应该可以工作。问题是,您需要确定要在数组的哪个维度上建立索引。看起来你想说X[:,:,X.sum2>12]-=1,因为你想处理的索引只有那些第三个索引的总和超过12的索引,第一个和第二个索引可以是任何东西。如果我理解你想做什么,那么转换回来是不可能的。您正在丢失信息,您正在将原始集映射到更小的子集。希望我能让事情变得更清楚一点。索引并不是导致我出现pita的原因。我不理解你的评论:你的帖子中有一个索引错误,我在下面的回答中更正了。我做了一个编辑,包括使用hstack和vstack,这将使您从三维阵列返回到正确的二维平铺。您必须在代码中注意概括数组维度的正确位置,例如,如果您有超过2x2的平铺。进行了一些更改,希望能使问题更清楚。您不清楚自己的问题是什么。您列出的代码的哪一步不适合您。NumPy确实有逻辑类型索引,一些类似X[X.sum2>12]的东西应该可以工作。问题是,您需要确定要在数组的哪个维度上建立索引。看起来你想说X[:,:,X.sum2>12]-=1,因为你想处理的索引只有那些第三个索引的总和超过12的索引,第一个和第二个索引可以是任何东西。如果我理解你想做什么,那么转换回来是不可能的。您正在丢失信息,您正在将原始集映射到更小的子集。希望我能让事情变得更清楚一点。索引并不是导致我出现pita的原因。我不理解你的评论:你的帖子中有一个索引错误,我在下面的回答中更正了。我做了一个编辑,包括使用hstack和vstack,这将使您从三维阵列返回到正确的二维平铺。您必须在代码中注意正确的位置,以概括数组的维度,例如,如果您有多个2x2平铺。进行了一些更改,希望能使问题更清楚。这有一个问题,即它不能推广到MxN平铺,其中平铺尺寸仍应为2x2,但较大的平铺图案大于2x2。如果能看到这段简洁的代码被修改以处理任意的KxP平铺(每个都是MxN),那就太好了。没有理由不进行概括,请参阅在我的答案末尾附加的示例上运行您的代码。您的代码给出了一个错误;我试过了。如果它是通过改变通话中的号码来重塑和转置的,然后,我上面的评论仍然适用-我认为您的方法只有在演示如何将平铺参数提供给重塑和转置代码,并将其用于平铺阵列(其中平铺也是通用形状的)时才有价值。请随时用这些信息更新答案,这并不太重要
坚固的如果你不明白,问一个新问题,我可能会回答。没关系。我已经对你的方法作了概括。我只是觉得你可能想提供这个答案。如果你没有,那没关系。我认为这是一个不完整的答案,但这只是我的观点,而且它不会减损您的方法在依赖优化的NumPy内置程序的简洁代码方面提供的好处。这有一个问题,即它不能推广到MxN平铺,其中平铺尺寸仍应为2x2,但较大的平铺图案大于2x2。如果能看到这段简洁的代码被修改以处理任意的KxP平铺(每个都是MxN),那就太好了。没有理由不进行概括,请参阅在我的答案末尾附加的示例上运行您的代码。您的代码给出了一个错误;我试过了。如果它是通过改变通话中的号码来重塑和转置的,然后,我上面的评论仍然适用-我认为只有当您演示如何向重塑和转置代码提供平铺参数,并将其应用于平铺阵列(其中平铺也是通用形状的),您的方法才有价值。请随时用这些信息更新答案,这并不难。如果你不明白,问一个新问题,我可能会回答。没关系。我已经对你的方法作了概括。我只是觉得你可能想提供这个答案。如果你没有,那没关系。我认为这是一个不完整的答案,但这只是我的观点,它并没有减损您的方法在依赖于优化的NumPy内置程序的简洁代码方面提供的好处。这种方法也会起作用,但bago的解决方案虽然还没有推广,但更优雅,应该更快。这种方法也会起作用,但bago的解决方案虽然还没有推广,但更优雅,应该更快。