pandas - 在 pandas 中尽快生成一个随机数字的列,平均值 = 20,最大值 = 25,最小值 = 5
问题描述
我有一个 df 如下所示
df = pd.DataFrame({'Session': ['s1', 's1', 's1', 's1', 's1', 's1', 's1',
's1', 's1', 's1', 's1', 's1', 's1', 's1', 's1'],
'slot_num': [1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9]})
东风:
Session slot_num
s1 1
s1 2
s1 3
s1 3
s1 4
s1 4
s1 5
s1 5
s1 6
s1 7
s1 7
s1 8
s1 8
s1 9
s1 9
从上面我想尽可能快地创建一个名为 service_time 的列,其平均值恰好为 20,最大值为 25,最小值为 2。
我尝试了下面的代码,但它并没有给出 20 的平均值。
注意:服务时间只能包含整数
# generate service time with mean = 20, min = 2 and max = 25
def gen_avg(n, expected_avg=20, a=2, b=25):
l = np.random.randint(a, b, size=n)
while True:
if np.mean(l) == expected_avg:
break
while np.mean(l) > expected_avg:
c = np.random.choice(np.where(l>expected_avg)[0])
l[c] = np.random.randint(a, expected_avg+1)
while np.mean(l) < expected_avg:
c = np.random.choice(np.where(l<expected_avg)[0])
l[c] = np.random.randint(expected_avg, b)
return l
df['service_time'] = df.groupby('Session')['Session'].transform(lambda x: gen_avg(len(x)))
我也尝试过低于一个,但需要很长时间
#https://stackoverflow.com/a/39435600/2901002
def gen_avg(n, expected_avg=20, a=5, b=25):
while True:
l = np.random.randint(a, b, size=n)
avg = np.mean(l)
if avg == expected_avg:
return l
df['service_time'] = df.groupby('Session')['Session'].transform(lambda x: gen_avg(len(x)))
解决方案
这可能需要很长时间,因为您期望平均值完全等于expected_avg
. 因为它是一个随机变量,其中一个n
观察值可以改变平均值,所以这是一个问题,尤其是随着n
增长。如果允许,您可以使用使平均值足够接近的方法,例如最多相差 5%。假设我们称之为tolerance
。尝试以下操作:
while abs((avg-expected_avg)/expected_avg) > tolerance:
l = np.random.randint(a, b, size=n)
avg = np.mean(l)
推荐阅读
- python-3.x - 如何比较具有不同 unicode 的两个字符串?
- python - PyXB:具有相同命名空间的两个版本的 XSD
- python - 如何在python中导入尚未在python中创建的东西?
- rest - 在 pentaho 中处理错误和休息响应的最佳方法是什么
- python - 如何从 Gitlab 获取当前时间?
- crash - 基于 Install4j 的安装程序挂起并退出,日志文件中的最后一条消息为“正在创建 jvm”
- android - 指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。使用芯片和芯片组
- android - 为什么有时谷歌播放库没有检测到最新版本
- cmake - CMAKE Build 使用 arm-none-eabi-gcc 编译器失败...“netinet/in.h:没有这样的文件或目录”和“--检查编译器是否接受 -pthread - no”
- php - 我想在按钮单击时将数据传递到下一页,并在使用 Ajax 重定向到它时