Python中的条件“至少”,带有伪随机化

2024-09-28 03:17:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我想做伪随机化,意思是通过遵守某些规则来随机化一些东西。你知道吗

想象一下下面的数据帧:

ColX 
 N
 N
 N
 N
 N
 N
 N
 N
 D
 D
 D

N代表中立,D代表偏离。在有一个越轨者之前,我希望至少有两个中性点(但是越轨者之间可以有更多的中性点),并且所有的东西都必须是随机的。你知道吗

结果:ColX应该看起来像

ColX
 N
 N
 D
 N
 N
 N
 D
 N
 N
 N
 D

我想知道我可以在python(pandas或其他包中的函数)或R(库中允许这个的任何函数)中使用什么样的函数你知道吗

先谢谢你。你知道吗


Tags: 数据函数pandas规则代表想象colx中性点
2条回答

以下是正确的方法。正确的意思是每一个合法的结合都是同样可能的。缺点是它比@BradSolomon的贵一点:

>>> def deviant_sep(N_D, N_N):
...     Didx = np.random.choice(N_N-N_D, N_D, replace=False)
...     out = np.zeros((N_N + N_D,), bool)
...     out[Didx] = True
...     Didx = np.flatnonzero(out[:N_N-N_D])
...     out[Didx] = False
...     out[Didx + np.arange(2, 2*N_D+2, 2)] = True
...     return np.array(['N', 'D'])[out.view(np.int8)]
... 
>>> deviant_sep(3, 8)
array(['N', 'N', 'D', 'N', 'N', 'N', 'N', 'D', 'N', 'N', 'D'],
      dtype='<U1')
>>> deviant_sep(3, 8)
array(['N', 'N', 'D', 'N', 'N', 'N', 'N', 'D', 'N', 'N', 'D'],
      dtype='<U1')
>>> deviant_sep(3, 8)
array(['N', 'N', 'D', 'N', 'N', 'N', 'D', 'N', 'N', 'D', 'N'],
      dtype='<U1')
>>>
>>> from timeit import repeat
>>> repeat('deviant_sep(1000, 8000)', globals=globals(), number=1000)
[0.2079479000531137, 0.20392047404311597, 0.20519483496900648]

解释:我怀疑是numpy的choice没有替换函数导致了这种速度变慢,我认为它会生成一个完整的置换,然后将其截断。你知道吗

该方法的工作原理如下:我们可以通过在每个D之前移除2 N来将nDDs和nN - 2 nDNs的合法模式映射到nDs和nN - 2 nDNs的模式,反之,通过在每个D之前插入2 Ns的合法模式。这张地图是1比1。以及我们知道如何以等概率绘制的无约束模式。所以我们这样做,然后映射到合法模式,在每个D之前插入2N。你知道吗

使用NumPy有一种方法可以实现这一点,itertools提供了一个微小的循环加速:

from itertools import repeat
import numpy as np


def gen_chunk(high=5):
    """Example: gen_chunk(high=6)  > array(['n', 'n', 'n', 'd']"""
    return np.append(np.repeat('n', np.random.randint(low=2, high=high)), 'd')


def gen_series(chunks=3, high=5):
    return np.concatenate([gen_chunk(high=high) for _ in repeat(None, 3)])


df = pd.DataFrame(gen_series())

演练:

您可以独立地生成由2个或多个N后跟1个D组成的每个“块”。这就是上面get_chunk()所做的。在本例中,它生成一个N的NumPy数组,后跟1 D,其中N的个数是一个介于2和high参数之间的随机整数。你知道吗

然后在gen_series()中,您可以构建单独的块(其中3个是这里的默认值)并将它们连接到单个1d数组中。你知道吗

更新

上面在每个块的生成中使用一个常量high参数。也许这不符合你正在寻找的psueorandom的定义。要对每个块生成使用不同的high,可以执行以下操作:

def gen_series(chunks, max_high):
    """Use a randomly selected `high` value for each chunk."""
    highs = np.random.randint(low=3, high=max_high, size=chunks)
    return np.concatenate([gen_chunk(high=high) for high in highs])

任何一种施工都应该相当快:

%timeit gen_series(chunks=1000, high=10)
# 36.9 µs ± 1.93 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

相关问题 更多 >

    热门问题