【问题标题】:Referencing a conditional random element of an array and replacing it引用数组的条件随机元素并替换它
【发布时间】:2015-05-23 23:41:42
【问题描述】:

这是我在 StackOverflow 上关于 Python/Numpy 编码的第二个问题。

我觉得肯定有某种函数可以执行伪代码:

np.random.choice([a[i-1,j],a[i+1,j],a[i,j-1],a[i,j+1]])==0 = 9

基本上,我希望随机函数选择与我相邻的单元格(上、下、左、右),值为 0,并用 9 替换所述单元格

不幸的是,我知道为什么我输入的代码是非法的。语句的前半部分返回一个 True/False 布尔值,因为我使用了比较/检查运算符。我无法将其设置为值 9。

如果我将代码加载分成两个代码并使用带有 random.choice 的 if 语句(查看等于零的相邻元素),那么在此之后,我需要某种函数或定义来回忆哪个单元格(左上或右上)是随机生成器最初选择的,然后我可以将其设置为 9。

亲切的问候,

编辑:我不妨附上一个示例代码,这样你就可以简单地运行它(我包括我的错误)

a = np.empty((6,6,))
a[:] = 0
a[2,3]=a[3,3]=a[2,4] = 1

for (i,j), value in np.ndenumerate(a):
     if a[i,j]==1:
          np.random.choice([a[i-1,j],a[i+1,j],a[i,j-1],a[i,j+1]])==0 = 9

【问题讨论】:

    标签: python arrays numpy random


    【解决方案1】:

    您可以从映射到二维数组中特定坐标移动的一系列方向(上、下、左、右)中进行选择,如下所示:

    # generate a dataset
    a = np.zeros((6,6))
    a[2,3]=a[3,3]=a[2,4] = 1
    
    # map directions to coordinate movements
    nesw_map = {'left': [-1, 0], 'top': [0, 1], 'right': [1,0], 'bottom': [0,-1]}
    directions = nesw_map.keys()
    
    # select only those places where a == 1
    for col_ind, row_ind in zip(*np.where(a == 1)):  # more efficient than iterating over the entire array
        x = np.random.choice(directions)
        elm_coords = col_ind + nesw_map[x][0], row_ind + nesw_map[x][1]
        if a[elm_coords] == 0:
            a[elm_coords] = 9
    

    请注意,这不会进行任何类型的边界检查(因此,如果1 出现在边缘,您可能会选择“偏离网格”的项目,这将导致错误)。

    【讨论】:

    • 再次感谢您的意见!我对字典和键不太熟悉,但你的例子真的很清楚!我有几个问题:我不明白 zip(*np.where()) 函数是如何运作的。为什么单独的 where 函数不够用?
    • @kevenren, np.where 将返回与数组中的维度一样多的列表。因此,二维数组 a==1 上的 where 将返回 2 列表,每个列表分别包含条件 a==1 为真时沿第一和第二轴的索引。我们将这些列表称为row_indicescol_indices。现在,在循环中,您只想查看这 2 个数组中的每个 pair 元素。所以你想组合这两个数组,类似于拉链的工作方式。尝试在交互式会话中建立这条线,看看会发生什么;在我看来,一个视觉示例可以更好地解释它。
    • 谢谢。这是非常有用的。星号将各个数组分隔成元组,然后 zip 将它们配对。
    【解决方案2】:

    这是获取所需内容的最“基本”方式(添加try/except 语句提供错误检查,因此您可以防止任何不需要的错误):

    import random,numpy
    a = numpy.empty((6,6,))
    a[:] = 0
    a[2,3]=a[3,3]=a[5,5] = 1
    
    for (i,j), value in numpy.ndenumerate(a):
        var = 0
        if a[i,j]==1:
            while var==0:
                x=random.randrange(0,4)                   #Generate a random number
                try:      
                    if x==0 and a[i-1,j]==0:              
                        a[i-1,j] =9                       #Do this if x = 0
                    elif x==1 and a[i+1,j]==0:            
                        a[i+1,j] =9                       #Do this if x = 1
                    elif x==2 and a[i,j-1]==0:             
                        a[i,j-1] =9                       #Do this if x = 2
                    elif x==3 and a[i,j+1]==0:            
                        a[i,j+1] =9                       #Do this if x = 3
                    var=1
                except:
                    var=0
    
    print a
    

    【讨论】:

    • 感谢您的意见!我想知道“尝试”的功能是什么。这是否相当于拥有一个 if 语句和一个更大的 else?
    • @kevenren,当算法发现例如1 在矩阵的边缘,例如右边缘。在这种情况下,如果随机选择为 3,a[i, j+1] 将产生错误,因为您正试图访问矩阵“外部”的元素。 可以用 if-else 语句代替,但在这种情况下最好使用 try-except,因为通常边缘元素的数量远小于元素的总数。看看EAFP principle
    猜你喜欢
    • 2015-10-02
    • 2019-03-15
    • 2021-12-31
    • 2017-07-19
    • 2020-11-30
    • 1970-01-01
    • 2016-10-10
    • 1970-01-01
    • 2014-05-05
    相关资源
    最近更新 更多