【问题标题】:Generating random numbers randomly随机生成随机数
【发布时间】:2018-07-17 06:18:11
【问题描述】:

我有一列T,它决定了值列中值的范围。 T 以 0.5 的步长递增,并且始终出现 4 次。

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

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

但是,每 10 个整数 Ts 中出现一次,即 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

【问题讨论】:

  • 我编辑了我的帖子。我希望现在更清楚了。
  • 这个函数应该是一个以 0.5 步递增计数 T 的生成器,还是在开始时给定 T a 的范围(例如,0.5
  • T 范围可以是任何东西,没关系。我的意思是,我们真的不需要考虑 T,我只想根据 T 生成值。您可以很容易地将 T 生成为列表。
  • “我想随机选择一个年份并且...”是什么意思?
  • 您是希望在第一批 100 个中恰好有一个“特殊”T,在第二批 100 个中另一个,等等,还是每个 T 出现“特殊”的概率为 1% ?

标签: python python-3.x numpy random


【解决方案1】:

我会这样做:

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

(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() 更快,但我不希望这样,因为您可能会以这种方式为每个条件(隐藏)一个循环。

编辑(基于 cmets)

如果您希望这更灵活,您可以尝试类似(假设您有一个预定义的数组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)

【讨论】:

  • 'T' 是预定义的。当“T”是 100 的倍数时,您提出的解决方案将在 15 到 16 之间选择一个值。我希望能够从 1 到 100 中随机选择一个“T”,其中“值”在 15 到 16 之间。
  • 如果我理解正确,你希望在(1, 100)范围内的单个随机数T,偏移量必须设置为15,同样对于T (1, 10) 范围,偏移量为 5。
  • 如果你需要为T的每10(或100)个数的每组更新随机的“幻数”,你必须写成生成器的形式,但它不能一个“函数”,或者你更新它后验。
  • 我希望最后的编辑为您提供了足够的信息以继续前进。我相信这会以您迄今为止描述的方式为您提供数据。我不太确定“随机性变化”是什么意思。原始问题中没有提到这一点。
  • 是的,感谢您的帮助!你给了我足够多的东西让我继续前进。通过“随机性变化”,我的意思是我生成一个介于 5 和 6 之间的随机数,而不是通常的 2 和 3。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    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 支持每个Nth 数字,偏移量为K。

    【讨论】:

    • 不。当 T=100 时,这将生成一个介于 15 和 16 之间的值。我想要一个随机函数来选择 T 值,该值应介于 15 和 16 之间。
    • 所以不是将 0、100、200... 映射到 (15,16),而是想要像 27、193、254... 这样的任意值?
    • 是的。 (5,6) 之间的映射也是如此。我希望将 4,17,29,33... 之类的东西映射到 (5,6)。
    • 您可以分别在 0 和 10 或 100 之间生成两个随机数 r1 和 r2,然后检查 if T % 100 == r2 并在之后为 r2 生成一个新值(对于 @ 也相同) 987654330@)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    相关资源
    最近更新 更多