numpy

时间:2017-07-19 20:29:59

标签: python numpy

尝试让我的代码更高效,更易读,而且我被卡住了。假设我想构建类似棋盘的东西,在8x8网格上交替使用黑白颜色。所以,使用numpy,我已经这样做了:

import numpy as np
board = np.zeros((8,8), np.int32)
for ri in range(8):
    for ci in range(8):
            if (ci + ri) % 2 == 0:
                    board[ri,ci] = 1

很好地输出:

array([[1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1]], dtype=int32)

然后我可以解析为白色方块或黑色方块。但是,实际上我的数组要大得多,而且这种方式非常低效且难以理解。我认为numpy已经解决了这个问题,所以我尝试了这个:

board = np.zeros(64, np.int32)
board[::2] = 1
board = board.reshape(8,8)

但输出错误,看起来像这样:

array([[1, 0, 1, 0, 1, 0, 1, 0],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [1, 0, 1, 0, 1, 0, 1, 0]], dtype=int32)

有没有更好的方法来实现我想要的效率(并且最好是可读的)?

注意:我没有附加到1和0,这可以很容易地用其他类型的值完成,即使是True / False或2种字符串,只要它有效

5 个答案:

答案 0 :(得分:4)

这是一种使用slicing进行正确启动并逐步增加2的方法 -

board = np.zeros((8,8), np.int32)
board[::2,::2] = 1
board[1::2,1::2] = 1

示例运行 -

In [229]: board = np.zeros((8,8), np.int32)
     ...: board[::2,::2] = 1
     ...: board[1::2,1::2] = 1
     ...: 

In [230]: board
Out[230]: 
array([[1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1]], dtype=int32)

其他棘手的方法 -

1)广播比较:

In [254]: r = np.arange(8)%2

In [255]: (r[:,None] == r)*1
Out[255]: 
array([[1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1]])

2)广播增加:

In [279]: r = np.arange(8)

In [280]: 1-(r[:,None] + r)%2
Out[280]: 
array([[1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1]])

答案 1 :(得分:2)

我自己找到了一个替代答案,所以在此发布以供将来参考任何感兴趣的人:

a = np.array([[1,0],[0,1]])
b = np.tile(a, (4,4))

结果:

array([[1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1, 0, 1]])

答案 2 :(得分:1)

我认为以下也是对变量输入进行操作的好方法

import sys
lines = sys.stdin.readlines()
n = int(lines[0])

import numpy as np
a = np.array([[1,0], [0,1]],dtype=np.int)
outputData= np.tile(a,(n//2,n//2))

print(outputData)

答案 3 :(得分:0)

您可以为单个偶数输入n

实现
import numpy as np
i = np.eye(2)
i = i[::-1]
k = np.array(i, dtype = np.int)
print(np.tile(k,(n//2,n//2)))

答案 4 :(得分:0)

我尝试并发现对于任何捐赠者编号来说,这都更短:

n = int(input())

import numpy as np

c = np.array([[0,1], [1, 0]])

print(np.tile(c, reps=(n//2, n//2)))