【问题标题】:2D array slicing by float value in Python在 Python 中按浮点值切片二维数组
【发布时间】:2017-05-31 18:34:34
【问题描述】:

我想在 Python 3.x 中按 x 值对 [x,y] 坐标对的数组进行切片,这与this 问题的解决方案类似,但使用坐标而不是一维列表。

例如,对于 (numpy) 坐标数组,我想要一个类似的函数:

coords = np.array([[1.5,10],[2.5,20],[3.5,30],[4.5,40],[5.5,50]])
def slice_coords_by_x(xmin, xmax, arr):
    *some function*
slice_coords_by_x(2, 4, arr)
>>>[[2.5,20],[3.5,30]]

如果解决方案包含或不包含 xmin 和 xmax,请不要过于挑剔,因为我将在超过 1000 左右的大范围内使用它。

【问题讨论】:

  • 所以你基本上要过滤?是否保证x坐标是有序的?

标签: python arrays python-3.x numpy slice


【解决方案1】:

切片并创建具有此类最小-最大限制的掩码,从而选择具有boolean-indexing 的行 -

def slice_coords_by_x(arr, xmin, xmax):
    return arr[(arr[:,0] >= xmin) & (arr[:,0] <= xmax)] 

示例运行 -

In [43]: arr
Out[43]: 
array([[  1.5,  10. ],
       [  2.5,  20. ],
       [  3.5,  30. ],
       [  4.5,  40. ],
       [  5.5,  50. ]])

In [44]: slice_coords_by_x(arr, xmin=2, xmax=4)
Out[44]: 
array([[  2.5,  20. ],
       [  3.5,  30. ]])

In [45]: slice_coords_by_x(arr, xmin=1, xmax=5)
Out[45]: 
array([[  1.5,  10. ],
       [  2.5,  20. ],
       [  3.5,  30. ],
       [  4.5,  40. ]])

【讨论】:

  • 感谢所有答案,感谢所有-选择这个纯粹是因为它不依赖于另一个包,并且它保留了 Python 自己的数组上的 numpy 数组类型
【解决方案2】:

如果没有numpy,您可以使用bisect 来查找插入点。请注意,该参数是一个列表(我添加了None 作为第二个参数,如here 中所示,但它没有用处)。

import bisect

coords = [[1.5,10],[2.5,20],[3.5,30],[4.5,40],[5.5,50]]

def slice_coords_by_x(lower,upper,arr):
    l=bisect.bisect_left(arr,[lower])
    u=bisect.bisect_right(arr,[upper])
    return arr[l:u]

print(slice_coords_by_x(2,4,coords))

结果:

[[2.5, 20], [3.5, 30]]

bisect 要求对列表进行排序(似乎是这种情况),否则将不起作用。

【讨论】:

  • 您不能简单地使用[lower] 代替[lower,None] 吗?至少对于bisect_left
  • 不:TypeError: unorderable types: list() &lt; int()
  • [lower] 仍然是list
  • 给定我查询bisect.bisect_left(arr,[2.5,None]),我得到TypeError: unorderable types: int() &lt; NoneType()... 上面定义的arr
  • 有趣。所以我链接到告诉None 的答案只是错误。等等:它只能是 python 2,因为你可以将字符串与整数等进行比较……在 python 3 中不再是这样了。
【解决方案3】:

无序

如果给定的点列表是无序的,您可以使用filter,并使用list实现:

def slice_coords_by_x(xmin,xmax,arr):
    return list(filter(lambda p: xmin < p[0] < xmax,arr))

您显然也可以将您的排序列表提供给此方法,但它会比下一种方法花费更多的时间。

排序列表

鉴于点按 x 坐标排序,您可以使用bisect 包:

def slice_coords_by_x(xmin,xmax,arr):
    left = bisect.bisect_left(arr,[xmin])
    right = bisect.bisect_right(arr,[xmax])
    return arr[left:right]

【讨论】:

    【解决方案4】:

    不应该简单

    def slice_coords_by_x(xmin, xmax, arr):
        return [i for i in arr if xmin <= i[0] and i[0] <= xmax]
    

    成功了吗?它可读、快速且易于访问。

    这个列表可以被排序,甚至可以传递一个数组,但是这个方法应该足够容易访问,可以根据任何需要进行更改。

    【讨论】:

    • if xmin &lt;= i[0] and i[0] &lt;= xmax => if xmin &lt;= i[0] &lt;= xmax 更好。不过,威廉的回答已经涵盖了这一点。
    • if xmin &lt;= i[0] and i[0] &lt;= xmaxif xmin &lt;= i[0] &lt;= xmax 实际上是一回事。
    • 可能,但后者更“pythonic”。
    • 我也不确定,Willems 的回答是否比我的更好。那么为什么我不应该写一个更容易阅读和理解的方式呢? PS.:我在Willem之前写了答案,实际上我之前将它作为评论输入,删除它,重新格式化并保存它,我之前没有看到Willem的答案。
    • 你在回答时必须更加积极;)
    猜你喜欢
    • 2020-12-03
    • 2015-01-17
    • 2013-04-12
    • 1970-01-01
    • 2011-09-19
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多