Python 使用numpy生成带有case-when条件的随机数据 问题:
我想生成要建模的数据。基于以下逻辑: 输入:2个名为Python 使用numpy生成带有case-when条件的随机数据 问题:,python,numpy,if-statement,Python,Numpy,If Statement,我想生成要建模的数据。基于以下逻辑: 输入:2个名为z和d的numpy数组 z:1d数组,值0/1 d:1d数组,值0/1 返回: y:1d数组。值:范数随机数 如果z==0,d==0,y~范数(1,1) 如果z==0,d==1,y~范数(0,1) 如果z==1,d==0,y~范数(1,1) 如果z==1,d==1,y~范数(2,1) 我想以一种超快速、清晰和类似蟒蛇的方式来做。 这似乎是基础数学和np。其中更快。在这种情况下,我只有3个条件(你们可以从基本数学部分清楚地看到)。若我有10个或更
z
和d
的numpy数组
z
:1d数组,值0/1
d
:1d数组,值0/1
返回:
y
:1d数组。值:范数随机数
如果z==0,d==0,y~范数(1,1)
如果z==0,d==1,y~范数(0,1)
如果z==1,d==0,y~范数(1,1)
如果z==1,d==1,y~范数(2,1)
我想以一种超快速、清晰和类似蟒蛇的方式来做。
这似乎是基础数学和np。其中更快。在这种情况下,我只有3个条件(你们可以从基本数学部分清楚地看到)。若我有10个或更多的条件,在If-else
语句中键入它们有时会令人困惑。我想进行数据模拟,这意味着我将在不同的n
下生成数百万次的数据。那么,最好的方法是什么
我所尝试的:
口述案情
输出:
每个回路16.2 ms±139µs(7次运行的平均值±标准偏差,每个100个回路)
简单的if-else
输出:
每个回路1.38 ms±22.1µs(7次运行的平均值±标准偏差,每个1000个回路)
基础数学
输出:
每个回路140µs±135 ns(7次运行的平均值±标准偏差,每个10000个回路)
np.在哪里
输出:
每个回路156µs±598 ns(7次运行的平均值±标准偏差,每个10000个回路)
还有其他新方法吗?看来你已经在这里做了准备工作。结果现在是基于权衡。上述所有解决方案都在不同程度上符合标准
这个代码是用来教别人的吗?也许一天只执行一到两次?它是一个更大的项目的一部分,需要非常清楚,以便其他人维护?如果是这种情况,请选择较慢但更易于理解和阅读的选项
它是每天执行数千次还是数百万次?资源成本降低产品利润的钱?如果是这样的话,请好好评论一下,并使用更快的选项
看来,基础数学
选项是最好的折衷方案,因为它简单易懂,而且执行速度快
我对每种方法的偏颇评价:
dict case when
:慢速,需要多次阅读/测试才能完全理解实际发生的情况,并找出是否存在任何未知问题
simple if else
:速度慢,需要多次阅读/测试才能完全理解实际发生的情况,并找出是否存在任何未知问题
基础数学
:如果你有一个小数学背景(应该包括大多数程序员),那么速度快,容易理解李>
np.where
:快速完成任务,需要多次阅读/测试才能完全理解实际发生的情况,但不太容易出错,因为它基于数组李>
以下是pythonic编写代码的哲学:
- 美胜于丑
- 显式比隐式好
- 简单总比复杂好
- 复杂总比复杂好
- 平的比嵌套的好
- 稀疏比密集好
- 可读性很重要
使用上述标准可以更容易地评估代码是否为pythonic。我认为最快的选择是通过将数组值参数用于normal
,只生成一次随机数。使用新的随机API:
import numpy as np
rng = np.random.default_rng()
# generate data
n = 2000
z = rng.binomial(1, 0.5, n)
d = rng.binomial(1, 0.5, n)
def generate_once(z, d):
"""Generate randoms for https://stackoverflow.com/questions/59676147"""
# encode mean; scale is always 1 anyway in the example
means = np.zeros_like(z, dtype=float)
z_inds = z == 0
d_inds = d == 0
means[d_inds] = 1
means[z_inds & ~d_inds] = 2
# generate the data
y = rng.normal(means)
return y
y = generate_once(z, d)
我并没有试着和其他人较量,但我希望这是有竞争力的。如果是“<代码> >,请考虑它是您的<代码>的一个更快的变体。在映射时使用快捷方式意味着
(一般来说,可以缩放
),因为一个数组可以减少开销,而且只生成一次正常的数字应该可以减少运行时间。我肯定你的如果没有
做你认为会做的事情,那么请确保你所有的选项都先做同样的事情。@AndrasDeak抱歉,我的帖子修改得更好了,但是你也应该仔细看看I==0&j==1
。
def myfun(x):
return {(0,1):np.random.normal(0,1),\
(0,0):np.random.normal(1,1),\
(1,0):np.random.normal(1,1),\
(1,1):np.random.normal(2,1)}[x]
%%timeit
y = [myfun(i) for i in zip(z,d)]
%%timeit
y = np.random.normal([0 if (i == 0) & (j ==1) else 2 if (i == 1) & (j == 1) else 1 for i,j in zip(z,d)],1)
%%timeit
h0 = np.random.normal(0,1,n)
h1 = np.random.normal(1,1,n)
h2 = np.random.normal(2,1,n)
y = (1-z)*d*h0 + (1-d)*h1 + z*d*h2
%%timeit
h0 = np.random.normal(0,1,n)
h1 = np.random.normal(1,1,n)
h2 = np.random.normal(2,1,n)
y = np.where((d== 0),h1,0) + np.where((z ==1) & (d== 1),h2,0) + np.where((z ==0) & (d== 1),h0,0)
import numpy as np
rng = np.random.default_rng()
# generate data
n = 2000
z = rng.binomial(1, 0.5, n)
d = rng.binomial(1, 0.5, n)
def generate_once(z, d):
"""Generate randoms for https://stackoverflow.com/questions/59676147"""
# encode mean; scale is always 1 anyway in the example
means = np.zeros_like(z, dtype=float)
z_inds = z == 0
d_inds = d == 0
means[d_inds] = 1
means[z_inds & ~d_inds] = 2
# generate the data
y = rng.normal(means)
return y
y = generate_once(z, d)