我想以不同的概率将'Y'
或'N'
附加到名为x
的list / numpy array / pandas series
上(例如,如果最后一个元素是'Y',则再次'Y'的概率为0.8,如果最后的元素是'N',则为0.5(。这是使用np.random.choice
完成的。我想做10万次。我已经为此编写了一个for
循环,但我不确定这是否是最快/最有效的方法。
# choose 'Y' or 'N' at random for first element
x = [np.random.choice(a = ['Y', 'N'])]
for i in range(10**6):
# append 'Y' or 'N' with probability dependent on x[-1] being 'Y' or 'N'
x.append(np.random.choice(a = ['Y', 'N'], p = [0.8, 0.2]) if x[-1] == 'Y' else np.random.choice(a = ['Y', 'N'], p = [0.5, 0.5]))
我想numpy select / where
和pandas shift / numpy roll
方法可能会有所帮助,但不知道如何(因为依赖于最后一个元素/上面的行使矢量化复杂化(
如有任何帮助,我们将不胜感激。谢谢
使用可以略有改进
x.append(np.random.choice(a = ['Y', 'N'], p = [0.8, 0.2]) if x[-1] == 'Y' else np.random.choice(a = ['Y', 'N']))
而不设置先前选择为"N"的情况下的概率。来自文档:
通过p设置用户指定的概率使用了一个比默认值更通用但效率更低的采样器。即使p的每个元素都是1/len(a(,通用采样器也会产生与优化采样器不同的样本。
我建议的解决方案是首先对之前选择的案例进行采样是而不是'N'(没有实际查看之前的选择,因为它还没有发生(,然后";正确的";对于以前的"Y":
# choose Y or N with p = [0.5, 0.5]
x = np.random.choice(a = ['Y', 'N'], size=10**6)
for i in range(1, 10**6):
# if x[-1] == 'Y' choose 'Y' or 'N' with p = [0.8, 0.2]
if x[-1] == 'Y':
x[i] = np.random.choice(a = ['Y', 'N'], p = [0.8, 0.2])
# if x[-1] == 'N' keep the actual value, chosen with p = [0.5, 0.5]
else: pass
使用%%timeit
,我每个循环得到304毫秒(5胜制(,而在原始代码中每个循环得到21.3秒(但警告"最慢的运行比最快的运行长74.03倍"(
使用%%time
,每次运行单元时结果都是可变的,但使用此版本时速度始终更快(上一个版本的CPU总时间为427毫秒,而不是23.4秒(。