我想做伪随机化,意思是通过尊重某些规则来随机化。
想象一下以下DataFrame:
ColX
N
N
N
N
N
N
N
N
D
D
D
N代表中立,D代表偏差。在拥有一个Deviant之前,我想至少有两个中立(但是在deviants之间可以有更多的中立)并且一切都必须是随机顺序。
结果:ColX应该看起来像
ColX
N
N
D
N
N
N
D
N
N
N
D
我想知道我可以在python(pandas或其他包中的函数)或R(允许这个的库中的任何函数)中使用哪种函数?)
提前谢谢。
答案 0 :(得分:3)
这是使用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数组。
<强>更新强>
以上在每个chunk的生成中使用常量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)
答案 1 :(得分:1)
这是&#34;正确&#34;这样做的方式。从某种意义上讲,每个法律组合同样可能是正确的。缺点是它比@BodSolomon的价格贵一点:
>>> 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
没有替换函数,我认为会产生一个完整的排列,然后截断它。
该方法的工作原理如下:我们可以将nD
D
和nN
N
s的合法模式映射到nD
{{1}的模式} s和D
nN - 2 nD
s通过在每个N
之前移除2 N
s,相反,通过插入2 D
将后一种模式转换为合法模式每个N
之前的s。这张地图是1比1。而无约束的模式我们知道如何以相同的概率绘制。因此,我们会这样做,然后通过在每个D
之前插入2 N
来映射到合法模式。