我想知道在给定某些条件的情况下,用数组中的其他随机元素替换数组中的元素的最有效方法是什么。更具体地说,我需要用该行中的另一个随机值替换每个不符合给定条件的元素。例如,我想将每一行数据替换为 data(row) 中介于 -.8 和 .8 之间的随机单元格。我的无效解决方案看起来像这样:
import numpy as np
data = np.random.normal(0, 1, (10, 100))
for index, row in enumerate(data):
row_copy = np.copy(row)
outliers = np.logical_or(row>.8, row<-.8)
for prob in np.where(outliers==1)[0]:
fixed = 0
while fixed == 0:
random_other_value = r.randint(0,99)
if random_other_value in np.where(outliers==1)[0]:
fixed = 0
else:
row_copy[prob] = row[random_other_value]
fixed = 1
显然,这效率不高。
最佳答案
我认为提取所有好的值会更快,然后在需要时使用 random.choice()
选择一个。像这样:
import numpy as np
import random
from itertools import izip
data = np.random.normal(0, 1, (10, 100))
for row in data:
good_ones = np.logical_and(row >= -0.8, row <= 0.8)
good = row[good_ones]
row_copy = np.array([x if f else random.choice(good) for f, x in izip(good_ones, row)])
您编写的高级 Python 代码比 Python 的 C 内部代码慢。如果您可以将工作下推到 C 内部,通常会更快。换句话说,尽量让 Python 为您完成繁重的工作,而不是编写大量代码。这是禅宗...编写更少的代码以获得更快的代码。
我添加了一个循环来运行您的代码 1000 次,并运行我的代码 1000 次,并测量它们执行所花费的时间。根据我的测试,我的代码快了十倍。
对这段代码的作用的补充说明:
row_copy
是通过构建一个新列表来设置的,然后在新列表上调用 np.array()
以将其转换为 NumPy 数组对象。新列表是通过列表理解构建的。
新榜单的制作规则是:好号保留;否则,从好的值中随机选择。
列表推导遍历一系列值,但要应用此规则,我们需要 两个 值:数字和表示该数字是否正确的标志。使列表理解同时遍历两个序列的最简单和最快的方法是使用 izip()
将两个序列“压缩”在一起。 izip()
将生成元组,一次一个,其中元组为 (f, x)
; f
在这种情况下是表示好与坏的标志,而 x
是数字。 (Python 有一个名为 zip()
的内置功能,它做的事情几乎相同,但实际上构建了一个元组列表;izip()
只是制作了一个迭代器产生元组值。但您可以在 Python 提示符下使用 zip()
来了解有关其工作原理的更多信息。)
在 Python 中,我们可以像这样将元组解压为变量名:
a, b = (2, 3)
在这个例子中,我们将 a
设置为 2,将 b
设置为 3。在列表理解中,我们从 izip()
解压元组进入变量 f
和 x
。
然后列表理解的核心是一个“三元 if”语句,如下所示:
a if flag else b
如果 flag
值为真,上面将返回值 a
,否则返回 b
。此列表理解中的一个是:
x if f else random.choice(good)
这实现了我们的规则。
关于python - Python 中的高效数组替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7352847/