如何从某些条件定义的子集中找到值的原始索引?

时间:2018-02-09 16:45:00

标签: python arrays numpy list-comprehension

我有一个值数组,我想从随机起点做某种形式的梯度下降/上升。如果我有一个值矩阵,例如:

board = np.array([[ 2.41791045, -1.70149254, -1.85074627, -1.46268657,],
                  [-1.70149254, -1.91044776, -1.94029851, -1.85074627],
                  [-1.85074627, -1.94029851, -1.91044776, -1.70149254],
                  [-1.46268657, -1.85074627, -1.70149254,  2.41791045]])

我想对随机起始索引的4个直接邻居进行抽样,并返回最大索引的索引。我可以通过使用起始索引-1,+ 1循环两次来轻松地对邻居进行采样。

如何查找原始数组的索引而不是我为了找到最大值而采样的值?在原始文件中搜索计算出的最大值并不总是有效,因为正如您在我的示例中所看到的,该数组是对称的。

我应该说我真的不想为每个方向手动创建if语句,因为我希望尽可能保持一般性,稍后我可能希望能够对其他站点进行采样或移动到3维。

编辑: 对不起,如果我在原帖中不是很清楚。最终目标是沿着值的梯度向下移动板直到达到出口点(在这种情况下是右上角和左下角)。因此,例如,如果我从位置(2,3)开始,给定示例中的值将为-1.701459。然后我想知道4个周围值中哪个最高,更重要的是索引是什么。我将采样的4个值将来自上方,下方,左侧和右侧(带有包装)。因此,如果我从位置(2,3)开始,则4个采样值将是板[1,3],板[3,3],板[2,2]和板[2,0]。

如果我想先将它们保存到单独的数组中,我将使用以下代码:

size = 4
start = np.random.randint(1, size - 1, 2)

samples = []
for x in (-1, 1):
    samples = np.append(samples, board[(start[0] + x) % size, start[1]])
for y in (-1, 1):
    samples = np.append(samples, board[start[0], (start[1] + y) % size])

optimalMove = max(samples)

但是我不仅仅想要最大值的值,我想知道它在数组“board”中的位置,但我不知道该怎么做。

最终编辑: 我已经解决了我的问题!

对于任何好奇我是如何做到的人: 首先,我创建了一个与我的板子形状相同的布尔掩码,然后我设置了我不想考虑的每个值为NaN。这是一个例子:

[[ 2.41791045         nan         nan         nan]
 [        nan -1.91044776         nan -1.85074627]
 [-1.85074627         nan         nan         nan]
 [        nan         nan         nan         nan]]

最后,我使用numpy的nanmax命令确定了最高值,并使用np.where获取了该值的索引。这也允许我创建一个包含所有等值邻居的数组,并从中随机选择。这是代码:

mask = np.ones_like(valueMatrix, dtype=bool)
for x in (-1, 1):
    mask[start[1], (start[0] + x) % size] = False
for y in (-1, 1):
    mask[(start[1] + y) % size, start[0]] = False

mask = mask.flatten()  # Flatten because np.nanmax() requires 1D arrays
dummyVal = valueMatrix.copy().flatten()
dummyVal[mask] = np.NaN
print(np.reshape(dummyVal, (size, size)))
position = np.where(dummyVal == np.nanmax(dummyVal))[0]

if len(position) > 1:  # Make sure only one value is chosen (at random)
    position = int(np.random.choice(position))

# These calculations convert the position value into co-ordinates to be used 
# as indices for the next move.
start = np.array([int(position % size), (int((position / size)))])

#  this whole thing goes in a while loop that continues until some exit 
#  position is landed on

1 个答案:

答案 0 :(得分:0)

您可以先分享一些您尝试过的代码吗? 另外,你的目标对我来说不是很清楚。 你想抽样4个邻居(我想象来自i-2的总共五个样本:i + 2)? 从这个集合中,您想要检索最大样本的索引吗?

如果这是正确的,我会这样做。

import numpy as np

# assuming idx is the desired index
def sample(board,idx, win):
    # creating a dummy variable here. You don't need this for your code
    board = np.array([[2.41791045, -1.70149254, -1.85074627, -1.46268657, ],
        [-1.70149254, -1.91044776, -1.94029851, -1.85074627],
        [-1.85074627, -1.94029851, -1.91044776, -1.70149254],
        [-1.46268657, -1.85074627, -1.70149254, 2.41791045]])

    tmp = idx - win + np.argmax(board.flatten()[idx - win:idx + win])
    max_idx = np.floor_divide(tmp, board.shape[0]), tmp % board.shape[0]
    max_val = board[max_idx]
    return (max_val, max_idx)
#sample(idx=10,win=2)
#(2,3)
在OP提供清晰度后

更新:

def sample(board=None,x=1,y=1, wlen=1):
    # creating a dummy variable here. You don't need this for your code
    if board is None:
        board = np.array([[2.41791045, -1.70149254, -1.85074627, -1.46268657, ],
                          [-1.70149254, -1.91044776, -1.94029851, -1.85074627],
                          [-1.85074627, -1.94029851, -1.91044776, -1.70149254],
                          [-1.46268657, -1.85074627, -1.70149254, 2.41791045]])
    x1=x-wlen
    x2=x+wlen
    y1=y-wlen
    y2=y+wlen

    x1=max(x1,0)
    x2=min(x2,board.shape[0])
    y1=max(y1,0)
    y2=min(y2,board.shape[1])

    grid = board[x1:x2,y1:y2]
    xy = np.unravel_index(grid.argmin(),grid.shape)
    min_val = grid[xy]
    min_xy = (x - wlen + xy[0], y - wlen + xy[1])

    return min_val,min_xy

#sample(x=2,y=3,wlen=1)
#(-1.9402985100000001, (1, 2))