简体   繁体   English

如何在python中的开始和结束坐标之间获得'n'个随机点?

[英]How to get 'n' random points between start and end coordinates in python?

I have a starting coordinate (x1,y1) and an ending coordinate (x2, y2).我有一个起始坐标 (x1,y1) 和一个结束坐标 (x2, y2)。 I want to generate 'n' random points between start and end coordinates without any duplicates.我想在开始和结束坐标之间生成“n”个随机点,没有任何重复。 How to do this with python?如何用python做到这一点?

I know that a simple way would be to generate 'n' x values and 'n' y values.我知道一种简单的方法是生成 'n' 个 x 值和 'n' 个 y 值。 So we get n*n pairs and I choose 'n' among them with no duplicates.所以我们得到 n*n 对,我在其中选择“n”,没有重复。 This way I mayn't get a uniform distribution of random points.这样我可能不会得到随机点的均匀分布。 Any other way to do this?还有其他方法可以做到这一点吗?

Edit: I require floating point coordinates in the rectangle formed by the start and end coordinates as opposite corners.编辑:我需要由开始和结束坐标形成的矩形中的浮点坐标作为对角。

TL;DR:特尔;博士:

from random import uniform


def gen_coords(x1, y1, x2, y2, n):
    result = set()
    # loops for each addition, avoiding duplicates
    while len(result) < n:
        result.add((uniform(x1, x2), uniform(y1, y2)))
    return result

Arguably, practically:可以说,实际上:

from random import uniform


def gen_coords(x1, y1, x2, y2, n):
    return [(uniform(x1, x2), uniform(y1, y2)) for _ in range(n)]

Considering that the odds of collisions are tiny.考虑到碰撞的几率很小。

Assuming that "between start and end coordinates" means in a rectangular section between these two corners in a Cartesian coordinate system (ie flat, 2D).假设“在开始和结束坐标之间”意味着在笛卡尔坐标系(即平面,2D)中这两个角之间的矩形部分。

And assuming that a "uniform distribution" is achieved sufficiently ignoring the non-uniform distribution of floating point values.并假设充分实现了“均匀分布”,而忽略了浮点值的非均匀分布。 (ie not the exact same number of floating point values on any interval of equal length, nor a constant distance between floating point values in a continuum) (即,在任何相等长度的区间上,浮点值的数量不是完全相同,也不是连续体中浮点值之间的恒定距离)

There's basically three ways of ensuring the randomly generated points are not duplicated:基本上有三种方法可以确保随机生成的点不重复:

  1. pick them from a collection of possible values, removing each pick to avoid picking it again;从一组可能的值中挑选它们,删除每个挑选以避免再次挑选;
  2. generate values within the allowed space, checking each pick against previous picks to avoid adding duplicates (and re-picking values until a new one is generated);在允许的空间内生成值,根据之前的选择检查每个选择以避免添加重复项(并重新选择值,直到生成新的值);
  3. generate values and add to the set until the desired set size, removing duplicates after generation if any and repeating the process until done.生成值并添加到集合中,直到达到所需的集合大小,生成后删除重复项(如果有)并重复该过程直到完成。

The first option can be a good choice if the space from which values are picked is of similar size to the target set size.如果从中选取值的空间与目标集大小相似,则第一个选项可能是一个不错的选择。 However, when picking points with random floating point coordinates in some space, this is unlikely.但是,当在某些空间中选择具有随机浮点坐标的点时,这是不太可能的。

The second choice is the most straightforward, but can be expensive to compute if the target set size is large, as every new pick causes more comparisons.第二种选择是最直接的,但如果目标集的大小很大,计算起来可能会很昂贵,因为每个新选择都会导致更多的比较。

The third choice is a bit more involved, but avoids comparisons until a candidate target set has been completed and certainly the best choice if the odds of collisions are small.第三种选择涉及更多,但避免比较,直到完成候选目标集,如果碰撞几率很小,这当然是最佳选择。

As a variant of the second choice, you could pick a target data structure that simply avoids the addition of duplicates altogether, relying on the language / interpreter to perform the checking more efficiently than any algorithm written in the language would be able to.作为第二种选择的变体,您可以选择一个目标数据结构,它完全避免添加重复项,依靠语言/解释器来执行比用该语言编写的任何算法更有效的检查。

In Python, this means using a set instead of a list , which is the fastest way to achieve the result and would likely be the way you'd check for duplicates in the third option anyway - so you may as well use it right away and go with the variant of the second option.在 Python 中,这意味着使用set而不是list ,这是获得结果的最快方法,并且可能是您在第三个选项中检查重复项的方式 - 所以您最好立即使用它使用第二个选项的变体。

Note that both the 2nd and 3rd option have a major flaw in case you're trying to create a set in the range of the selection function that's larger than the domain of the selection function.请注意,如果您尝试在大于选择函数域的选择函数范围内创建集合,则第二个和第三个选项都有一个主要缺陷。 But for the given problem that's unlikely except for extremely large 'n'.但是对于给定的问题,除了极大的“n”之外不太可能。

A solution (pitting the second option against the third):一个解决方案(将第二个选项与第三个选项进行对比):

from random import uniform
from timeit import timeit


def pick_coords_restricted(x1, y1, x2, y2, n):
    result = set()
    # loops for each addition, avoiding duplicates
    while len(result) < n:
        result.add((uniform(x1, x2), uniform(y1, y2)))
    return result


def pick_coords_checked(x1, y1, x2, y2, n):
    result = []
    # loops once for attempt, checking after each iteration
    while len(set(result)) < n:
        if len(result) > 0:
            result = list(set(result))
            result += [(uniform(x1, x2), uniform(y1, y2)) for _ in range(n - len(result))]
        else:
            result = [(uniform(x1, x2), uniform(y1, y2)) for _ in range(n)]
    return result


print(timeit(lambda: pick_coords_restricted(0, 0, 1, 1, 1000), number=10000))
print(timeit(lambda: pick_coords_checked(0, 0, 1, 1, 1000), number=10000))

Result (on my hardware):结果(在我的硬件上):

4.3799341
3.9363368000000003

I get consistently, but marginally better results for the pick_coords_checked function - I would favour the clarity of the first implementation.对于pick_coords_checked函数,我得到了一致但稍微好一点的结果 - 我更喜欢第一个实现的清晰度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM