【问题标题】:Python 3.1- Grid Simulation Conceptual issuePython 3.1- 网格模拟概念问题
【发布时间】:2011-02-02 04:27:38
【问题描述】:

目标是将一维数组视为二维网格。第二个一维数组给出了网格中需要更改的值的列表,第三个数组指示了多少。

问题是修改后的值周围的值也发生了变化。

下面的示例保留为 1D 数组,但对其进行计算时就好像它是 2D 网格一样。有用;但目前它会更改网格中与一维列表(示例)中的值匹配的所有值。对于列表中的 1 个值,我不想只转换 1 个值及其周围环境。

即如果列表是[2,3];我只想更改迭代中遇到的第一个 2 和 3 值。目前的例子,在网格中每 2 改变一次。

让我感到困惑的是(可能是因为我构建修改计算的方式),我不能简单地遍历网格并在每次匹配时删除列表值。

提前感谢您的宝贵时间!!

代码如下;

import numpy

def grid_range(value):
    if value > 60000:
        value = 60000
        return (value)
    elif value < 100:
        value = 100
        return(value)
    elif value <= 60000 and value >= 100:
        return(value)


def grid(array,samples,details):

    original_length = len(array)
    c = int((original_length)**0.5)

    new_array = []                                                                  #create a new array with the modified values

    for elem in range (len(array)):                                                 #if the value is in samples
        if array[elem] in samples:
            value = array[elem] + (array[elem] * (details[1]/100))
            test_range = grid_range(value)
            new_array.append(test_range)

        elif ((elem + 1) < original_length) and array[elem - 1] in samples:                                          #change the one before the value                                 
            if (len(new_array) % c == 0) and array[elem + 1] not in samples:                             
                new_array.append(array[elem])
            else:
                new_forward_element = array[elem] +(array[elem] * (details[2]/100))   
                test_range1 = grid_range(new_forward_element)
                new_array.append(test_range1)

        elif ((elem + 1) < original_length) and (array[elem + 1]) in samples:       #change the one before and that it doesn't attempt to modify passed the end of the array                                 
            if (len(new_array) + 1) % c == 0:
                new_array.append(array[elem])
            else:
                new_back_element = array[elem] +(array[elem] * (details[2]/100))
                test_range2 = grid_range(new_back_element)    
                new_array.append(test_range2)

        elif ((elem+c) <= (original_length - c))and(array[elem + c]) in samples:    #if based on the 9 numbers on the right of the keyboard with test value numebr 5; this is position '2' 
            extra1 = array[elem] +(array[elem] * (details[2]/100))
            test_range3 = grid_range(extra1)
            new_array.append(test_range3)

        elif (array[abs(elem - c)]) in samples:                                     #position '8'
            extra2 = array[elem] +(array[elem] * (details[2]/100))
            test_range4 = grid_range(extra2)
            new_array.append(test_range4)

        elif (array[abs(elem - (c-1))]) in samples:                                 #position '7' 
            if (elem - (c-1)) % c == 0:
                new_array.append(array[elem])
            else:
                extra3 = array[elem] +(array[elem] * (details[2]/100))
                test_range5 = grid_range(extra3)
                new_array.append(test_range5)

        elif (array[abs(elem - (c+1))]) in samples:                                 #position '9'    
            if (elem - (c+1) + 1) % c == 0:
                new_array.append(array[elem])

            else:
                extra4 = array[elem] +(array[elem] * (details[2]/100))
                test_range6 = grid_range(extra4) 
                new_array.append(test_range6)

        elif ((elem +(c-1)) < original_length) and (array[elem + (c-1)]) in samples:    #position '1', also not passed total array length
            if (elem + (c-1)+ 1) % c == 0:
                new_array.append(array[elem])
            else:            
                extra5 = array[elem] +(array[elem] * (details[2]/100))
                test_range7 = grid_range(extra5)
                new_array.append(test_range7)

        elif (elem + (c+1)) < (len(array)- c) and (array[elem + (c+1)]) in samples:     #position '3', also not passed total array length
            if (elem + (c+1)) % c == 0:
                new_array.append(array[elem])
            else:
                extra6 = array[elem] +(array[elem] * (details[2]/100))
                test_range8 = grid_range(extra6)
                new_array.append(test_range8)

        else:
            new_array.append(array[elem])

    return(new_array)


a = [16,2,20,4,14,6,70,8,9,100,32,15,7,14,50,20,17,10,9,20,7,17,50,2,19,20]
samples = [2]
grid_details = [10,50,100]

result = grid(a,samples,grid_details)

编辑:

根据您的回答 Joe,我创建了一个版本,该版本将主要值(中心)修改为特定的 %,并将周围的元素修改为另一个。但是,如何确保在下一次样本迭代期间不会再次转换更改的值。

感谢您的宝贵时间!

示例代码:

def grid(array,samples,details):

    #Sides of the square (will be using a squarable number
    Width = (len(array)) ** 0.5
    #Convert to grid
    Converted = array.reshape(Width,Width)
    #Conversion details
    Change = [details[1]] + [details[2]] 
    nrows, ncols = Converted.shape

    for value in samples:

        #First instance where indexing returns it
        i,j  = np.argwhere(Converted == value)[0]

        #Prevent indexing outside the boudaries of the
        #array which would cause a "wraparound" assignment
        istart, istop = max(i-1, 0), min(i+2, nrows)
        jstart, jstop = max(j-1, 0), min(j+2, ncols)


        #Set the value within a 3x3 window to their "new_value"  
        for elem in Converted[istart:istop, jstart:jstop]:

        Converted[elem] = elem + (elem * (value * ((Change[1]/100))

        #Set the main value to the new value  
        Converted[i,j] = value + (value * ((Change[0])/100))


    #Convert back to 1D list
    Converted.tolist()

    return (Converted)


a =  [16,2,20,4,14,6,70,8,9,100,32,15,7,14,50,20,17,10,9,20,7,17,50,2,19,20,21,22,23,24,25]
samples = [2, 7]
grid_details = [10,50,100]

result = grid(a,samples,grid_details)

print(result)

PS:我不想避免修改网格中的任何值,之前已经修改过,无论是主值还是周围值。

【问题讨论】:

    标签: python python-3.x simulation


    【解决方案1】:

    首先,我不太清楚你在问什么,如果我完全误解了你的问题,请原谅我......

    您说您只想修改等于给定值的第一项,而不是全部。如果是这样,您需要在找到第一个值后添加break,否则您将继续循环并修改所有其他值。

    但是,有更好的方法来做你想做的事。

    另外,您在顶部导入 numpy,然后从不(?)使用它...

    这正是你想用 numpy 做的事情,所以我将举一个使用它的例子。

    您似乎只是将一个函数应用于二维数组的 3x3 移动窗口,其中数组的值与某个给定值匹配。

    如果我们想将给定索引周围的 3x3 区域设置为某个值,我们只需执行以下操作:

    x[i-1:i+1, j-1:j+1] = value 
    

    ...其中x 是您的数组,ij 是行和列,value 是您要设置它们的值。 (类似地,x[i-1:i+1, j-1:j+1] 返回 &lt;i,j&gt; 周围的 3x3 数组)

    此外,如果我们想知道&lt;i,j&gt; 表示特定值出现在数组中的位置,我们可以使用numpy.argwhere,它将返回&lt;i,j&gt; 表示给定条件为真的每个位置的列表.

    (在 numpy 数组上使用条件会生成一个布尔数组,显示条件是真还是假。因此,x &gt;= 10 将生成一个与 x 形状相同的布尔数组,不是 只需 TrueFalse。这让您可以做一些不错的事情,例如 x[x&gt;100] = 10 设置 x 中高于 100 到 10 的所有值。)

    总而言之,我相信这个 sn-p 做了你想做的事:

    import numpy as np
    
    # First let's generate some data and set a few duplicate values
    data = np.arange(100).reshape(10,10)
    data[9,9] = 2
    data[8,6] = 53
    
    print 'Original Data:'
    print data
    
    # We want to replace the _first_ occurences of "samples" with the corresponding
    # value in "grid_details" within a 3x3 window...
    samples = [2, 53, 69]
    grid_details = [200,500,100]
    
    nrows, ncols = data.shape
    for value, new_value in zip(samples, grid_details):
        # Notice that were're indexing the _first_ item than argwhere returns!
        i,j = np.argwhere(data == value)[0]
    
        # We need to make sure that we don't index outside the boundaries of the
        # array (which would cause a "wraparound" assignment)
        istart, istop = max(i-1, 0), min(i+2, nrows)
        jstart, jstop = max(j-1, 0), min(j+2, ncols)
    
        # Set the value within a 3x3 window to be "new_value"
        data[istart:istop, jstart:jstop] = new_value
    
    print 'Modified Data:'
    print data
    

    这会产生:

    Original Data:
    [[ 0  1  2  3  4  5  6  7  8  9]
     [10 11 12 13 14 15 16 17 18 19]
     [20 21 22 23 24 25 26 27 28 29]
     [30 31 32 33 34 35 36 37 38 39]
     [40 41 42 43 44 45 46 47 48 49]
     [50 51 52 53 54 55 56 57 58 59]
     [60 61 62 63 64 65 66 67 68 69]
     [70 71 72 73 74 75 76 77 78 79]
     [80 81 82 83 84 85 50 87 88 89]
     [90 91 92 93 94 95 96 97 98  2]]
    
    Modified Data:
    [[  0 200 200 200   4   5   6   7   8   9]
     [ 10 200 200 200  14  15  16  17  18  19]
     [ 20  21  22  23  24  25  26  27  28  29]
     [ 30  31  32  33  34  35  36  37  38  39]
     [ 40  41 500 500 500  45  46  47  48  49]
     [ 50  51 500 500 500  55  56  57 100 100]
     [ 60  61 500 500 500  65  66  67 100 100]
     [ 70  71  72  73  74  75  76  77 100 100]
     [ 80  81  82  83  84  85  50  87  88  89]
     [ 90  91  92  93  94  95  96  97  98   2]]
    

    最后,您提到您希望“将某事物同时视为 N 维数组和“平面”列表”。这在某种意义上已经是 numpy 数组了。

    例如:

    import numpy as np
    
    x = np.arange(9)
    y = x.reshape(3,3)
    
    print x
    print y
    
    y[2,2] = 10000
    
    print x
    print y
    

    这里,yx 的“视图”。如果我们更改y 的元素,我们将更改x 的相应元素,反之亦然。

    同样,如果我们有一个 2D 数组(或 3D、4D 等),我们希望将其视为“平面”一维数组,您可以调用 flat_array = y.ravel(),其中 y 是您的 2D 数组。

    希望对您有所帮助,无论如何!

    【讨论】:

    • 这非常好,几乎是我想要的。感谢您的宝贵时间!
    • 我还有一个与此相关的问题。请看下文。
    【解决方案2】:

    您没有指定必须以任何特定方式执行此操作,因此我假设您愿意接受建议。 一种完全不同(恕我直言更简单)的方法是创建一个数组数组:

    grid = [[0,0,0,0,0],
            [0,0,0,2,0],
            [1,0,0,0,0],
            [0,0,0,0,0],
            [0,0,3,0,0]]
    

    要访问网格上的位置,只需提供列表的索引(行),然后提供该网格上的位置索引(列)。例如:

    1 = grid[2][0]
    2 = grid[1][3]
    3 = grid[4][2]
    

    创建非硬编码网格(例如可变大小):

    def gridder(width,height):
        list = []
        sublist = []
        for i in range(0,width):
            sublist.append(1)
        for i in range(0,height):
            list.append(sublist)
        return list
    

    修改网格的一部分:

    def modifier(x,y,value):
        grid[y][x] = value
    

    *如果这是家庭作业,并且您应该按照答案中指定的方式完成,那么您可能无法使用此答案。

    【讨论】:

    • 帮助我理解,感谢您的评论和时间!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 2011-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多