使用 Python 根据阈值选择值

Selecting values based on threshold using Python

通过扫描同一行和后续行中的相邻元素,当前代码 select 的最小值。但是,如果代码小于阈值,我希望代码 select 所有值。例如,在第 2 行中,我希望代码同时选择 0.86 和 0.88,因为两者都小于 0.9,而不仅仅是 0.86、0.88 中的最小值。基本上,如果所有相邻元素都大于阈值,代码应该选择最小值。如果不是这种情况,它应该选择所有小于阈值的值。

import numpy as np
import numba as nb

Pe = np.random.rand(5,5)

def minValues(arr):
    n, m = arr.shape
    assert n >= 1 and m >= 2
    res = []
    i, j = 0, np.argmin(arr[0,:])
    res.append((i, j))
    iPrev = jPrev = -1
    while iPrev < n-1:
        cases = [(i, j-1), (i, j+1), (i+1, j)]
        minVal = np.inf
        iMin = jMin = -1
        # Find the best candidate (smallest value)
        for (i2, j2) in cases:
            if i2 == iPrev and j2 == jPrev: # No cycles
                continue
            if i2 < 0 or i2 >= n or j2 < 0 or j2 >= m: # No out-of-bounds
                continue
            if arr[i2, j2] < minVal:
                iMin, jMin = i2, j2
                minVal = arr[i2, j2]
        assert not np.isinf(minVal)
        # Store it and update the values
        res.append((iMin, jMin))
        iPrev, jPrev = i, j
        i, j = iMin, jMin
    return np.array(res)

T=minValues(Pe)
Path=Pe[T.T[0], T.T[1]]

当前输出:

期望的输出:

试试这个:

def minValues(arr):
  n, m = arr.shape
  assert n >= 1 and m >= 2
  res = []
  i, j = 0, np.argmin(arr[0,:])
  print(f"Values i, j are: {i}, {j}")
  res.append((i, j))
  iPrev = jPrev = -1
  while iPrev < n-1:
      lowerVals = []
      print(f"Values iPrev, jPrev are: {iPrev}, {jPrev}")
      cases = [(i, j-1), (i, j+1), (i+1, j)]
      print(f"Posible cases are: {cases}")
      minVal = np.inf
      print(f"MinVal is: {minVal}")
      iMin = jMin = -1
      # Find the best candidate (smallest value)
      for (i2, j2) in cases:
          if i2 == iPrev and j2 == jPrev: # No cycles
              continue
          if i2 < 0 or i2 >= n or j2 < 0 or j2 >= m: # No out-of-bounds
              continue
          if arr[i2, j2] < arr[i, j]:
              lowerVals.append((i2, j2))
          if arr[i2, j2] < minVal:
              iMin, jMin = i2, j2
              minVal = arr[i2, j2]
      if not lowerVals: lowerVals.append((iMin, jMin))
      print(f"Values iMin, jMin are: {iMin}, {jMin}")    
      print(f"MinVal is: {minVal}")
      print(f"Lower values are: {lowerVals}")
      assert not np.isinf(minVal)
      # Store it and update the values
      res += lowerVals
      print(f"Final res after current iteration: {res}\n")
      iPrev, jPrev = i, j
      i, j = iMin, jMin
  return np.array(res)

我使用打印进行调试,但我只是在每次迭代中检查所有低于当前值的值,并在迭代结束时将它们添加到路径中。

编辑:引入我评论的额外行你得到上面的代码,这应该可以工作。

这是一个有趣的问题-看水文flow/downhill方向?

描述的问题是您没有指定哪个相邻单元格迭代到下一个,这意味着,如果您有三个较低的相邻单元格,它们所有都被添加到输出数组,但哪个被选中了?此外,当回顾输出数组时,您如何知道相对于单个相邻单元格添加了哪些?我通过选择小于源单元格值(最大下降)的相邻单元格的最低值来解决这个问题,然后从该单元格继续搜索等等。对于每次迭代,都有一个新的嵌套列表,其中包含较低的相邻单元格的单元格位置。这可以很容易地以多种方式更新,包括导出一个额外的列表,显示哪些单元格用于搜索(基本上是所采用的路径,同时可能有突出显示的单元格(下方)本身未被访问。

import numpy as np

Pe = np.random.rand(5,5)

def nearestMin(arr, output_arr=[[0,0]], n=0, m=0):
    if m==arr.shape[1]:
        return output_arr
    lower_vals = np.argwhere(arr < arr[n,m])
    if lower_vals.size == 0:  #No values anywhere less than current cell
        return output_arr
    #Get offset from current point, as tuple of x and y distance
    smaller_adjacents = np.where(Pe < Pe[n, m])
    if smaller_adjacents[0].size == 0:  #No lower points anywhere
        return output_arr 
    ind = np.where((abs(n - smaller_adjacents[0]) <= 1 ) & \
        (abs(m - smaller_adjacents[1]) <= 1))[0] 
    if ind.size == 0:  #No lower points neighboring
        return output_arr
    xs, ys = smaller_adjacents[0][ind], smaller_adjacents[1][ind]
    lower_neighbors = np.vstack((xs, ys)).T.tolist()
    output_arr.append(lower_neighbors) #Unbracket to have final output array be flat (2d)
    n_depth = [Pe[x,y] for x,y in lower_neighbors] - Pe[n,m]
    biggest_drop = np.where(n_depth==n_depth.min())[0][0]
    lowest_neighbor = lower_neighbors[biggest_drop]
    return nearestMin(arr, output_arr, n=lowest_neighbor[0], m=lowest_neighbor[1])

nearestMin(Pe)

如果您想要路径,可以将相同的代码修改为 return 作为第二个数组,如下所示。在此示例中,列出了路径的值。每个值对应于相邻较低值的第一个 returned 数组中的“列表列表”项。同样,不确定您要做什么。

import numpy as np

Pe = np.random.rand(5,5)

def nearestMin(arr, output_arr=[[0,0]], path=[], n=0, m=0):
    #Initialize path variable properly
    if output_arr == [[0,0]]:
        path.append(arr[0,0])
    if m==arr.shape[1]:
        return (output_arr, path)
    lower_vals = np.argwhere(arr < arr[n,m])
    if lower_vals.size == 0:  #No values anywhere less than current cell
        return (output_arr, path)
    #Get offset from current point, as tuple of x and y distance
    smaller_adjacents = np.where(Pe < Pe[n, m])
    if smaller_adjacents[0].size == 0:  #No lower points anywhere
        return (output_arr, path)
    ind = np.where((abs(n - smaller_adjacents[0]) <= 1 ) & \
        (abs(m - smaller_adjacents[1]) <= 1))[0] 
    if ind.size == 0:  #No lower points neighboring
        return (output_arr, path)
    xs, ys = smaller_adjacents[0][ind], smaller_adjacents[1][ind]
    lower_neighbors = np.vstack((xs, ys)).T.tolist()
    output_arr.append(lower_neighbors) #Unbracket to have final output array be flat (2d)
    n_depth = [Pe[x,y] for x,y in lower_neighbors] - Pe[n,m]
    biggest_drop = np.where(n_depth==n_depth.min())[0][0]
    lowest_neighbor = lower_neighbors[biggest_drop]
    path.append(arr[lowest_neighbor[0], lowest_neighbor[1]])
    return nearestMin(arr, output_arr, path, n=lowest_neighbor[0], m=lowest_neighbor[1])
    

nearestMin(Pe)