随机生成随机数

时间:2018-07-17 06:18:12

标签: python python-3.x numpy random

我有一个列T,该列决定value列中值的范围。 T以0.5的步长递增,并且总是出现4次。

如果T=0.5,1.5,2.5等,我想生成一个1到2之间的随机数。 如果是T=1,2,3,4等,我想生成一个2到3之间的随机数。

^这很简单,切换随机数发生器或分别生成随机数并对其进行排序应该可以解决问题。

但是,我希望每10个整数T中有一次,即1,2,3,4...10,我希望随机函数选择一个随机的T并将值设置为5到6,而不是2和3.

类似地,我想在T的每100个整数值中选择一次,并随机选择一个T并使Value列在15到16之间。

T   Value
0.5 1.01
0.5 1.05
0.5 1.85
0.5 1.49
1   2.45
1   2.52
1   2.48
1   2.95
1.5 1.78
1.5 1.45
1.5 1.65
1.5 1.77
2   2.96
2   2.75
2   2.74
2   2.95
2.5 1.75
2.5 7.89
2.5 1.33
2.5 1.58
3   5.78
3   5.44
3   5.36
3   5.24

3 个答案:

答案 0 :(得分:1)

我会这样:

EDIT :我更改了最后两个条件,因为它们实际上是多余的。)

EDIT2 :我进行了更新,以便10/100偏移量更改随机发生-但在函数定义中设置一次。)

import random

def rand_gen_t(
        t,
        n0=random.randint(1, 100),
        n1=random.randint(1, 10)):
    if t % n0 == 0:
        offset = 15
    elif t % n1 == 0:
        offset = 5
    elif t % 1 == 0:
        offset = 1
    elif t % 0.5 == 0:
        offset = 2
    return offset + random.random()

与@DillonDavis提出的解决方案相比,只要它是半整数值,它就可以适用于任意t,并且假定您感兴趣的范围始终为1,并且唯一改变的是偏移量(根据您的问题的内容,这是正确的。)

我将为您定义其他输入值应该做什么。

如果您希望它能够按照您的标签建议处理numpy.ndarray,我将使用np.vectorize函数修饰符,例如:

import numpy as np

rand_gen_t_arr = np.vectorize(rand_gen_t)

在时间上,拟议的Numpy解决方案在这里并不会真正发挥作用,但也不是那么糟糕:

%timeit [rand_gen_t(x / 2) for x in range(1000)]
# 1000 loops, best of 3: 490 µs per loop

%timeit rand_gen_t_arr(np.arange(1000) / 2)
# 1000 loops, best of 3: 523 µs per loop

也许使用np.where()的速度更快,但是我不希望这样,因为您可能会以这种方式(隐藏)每个条件的循环。

编辑(基于评论)

如果您希望此方法更加灵活,可以尝试执行以下操作(假设您有一个预定义的数组t_arr,其中包含值T):

import numpy as np

# I assume that you have it somehow, but I generate one for completeness
t_arr = np.arange(1, 1000) / 2

# first generate random numbers between 0 and 1
val_arr = np.random.random(t_arr.shape)

# update for values of `T`
int_mask = np.where(t_arr % 1 == 0)[0]
half_int_mask = np.where(t_arr % 0.5 == 0)[0]
int_offset = 1
half_int_offset = 2
val_arr[int_mask] += int_offset
val_arr[half_int_mask] += half_int_offset


# update `Value` for exceptional cases
def gen_special_mask(n_special, n_max):
    return np.random.randint(1, n_special, int(n_max / n_special)) + np.arange(0, n_max, n_special)


def mask_intersect(mask1, mask2):
     return np.array(list(set(mask1).intersection(set(mask2))))

special_mask10 = gen_special_mask(10, val_arr.size)
special10_offset = 5
special_mask100 = gen_special_mask(100, val_arr.size)
special100_offset = 10

special_mask10_int = mask_intersect(int_mask, special_mask10)
val_arr[special_mask10_int] += (special10_offset - int_offset)
special_mask10_half_int = mask_intersect(half_int_mask, special_mask10)
val_arr[special_mask10_half_int] += (special10_offset - half_int_offset)

special_mask100_int = mask_intersect(int_mask, special_mask10)
val_arr[special_mask100_int] += (special100_offset - int_offset)
special_mask100_half_int = mask_intersect(half_int_mask, special_mask10)
val_arr[special_mask100_half_int] += (special100_offset - half_int_offset)

答案 1 :(得分:0)

如果我对您的理解正确,我认为这听起来像您想使用开关盒。只需运行第一个随机函数,然后设置运行另一个随机函数的开关(第二个随机函数将根据第一个结果而变化)。

在使用Python时,此开关可能更适合仅用作一系列if语句,或者您可以在this article.中看到有关其他示例实现的文档,只需将其映射的函数包括在内即可。其中的第二个随机函数。

答案 2 :(得分:0)

我相信您正在寻找以下内容:

from random import random

def rand(T):
    bounds = None
    if T % 100 == 0:
        bounds = (15, 16)
    elif T % 10 == 0:
        bounds = (5, 6)
    elif T in [1, 2, 3]:
        bounds = (2, 3)
    elif T in [0.5, 1.5, 2.5]:
        bounds = (1, 2)

    lower, upper = bounds
    return random() * (upper - lower) + lower

您可以使用T in [...]语法支持任意数字列表,并使用T % N == K支持第N个数字,其偏移量为K