Python中的高效数组替换

Posted

技术标签:

【中文标题】Python中的高效数组替换【英文标题】:Efficient Array replacement in Python 【发布时间】:2011-11-13 05:58:48 【问题描述】:

我想知道在给定一些标准的情况下,用数组中的其他随机元素替换数组中的元素的最有效方法是什么。更具体地说,我需要用该行中的另一个随机值替换每个不符合给定条件的元素。例如,我想将每一行数据替换为 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

显然,这效率不高。

【问题讨论】:

【参考方案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() 只是创建了一个生成元组值的迭代器。但是您可以在zip() 处玩Python 提示,以了解有关其工作原理的更多信息。)

在 Python 中,我们可以将元组解压成变量名,如下所示:

a, b = (2, 3)

在本例中,我们将a 设置为2,将b 设置为3。在列表推导中,我们将izip() 中的元组解包为变量fx

那么列表推导的核心是一个“三元 if”语句,如下所示:

a if flag else b

如果flag 的值为真,以上将返回值a,否则返回b。此列表理解中的一项是:

x if f else random.choice(good)

这实现了我们的规则。

【讨论】:

我非常感谢这个答案。如果你有时间,你能解释一下这条线在做什么吗? row_copy = np.array([x if f else random.choice(good) for f, x in izip(good_ones, row)]) 当然。我会把解释放在答案中;见上文。

以上是关于Python中的高效数组替换的主要内容,如果未能解决你的问题,请参考以下文章

无需替换的内存高效随机数迭代器

python基于组合逻辑判断替换numpy数组中的满足条件的元素相等判断替换numpy数组中的指定数值为另一个数值大小判断替换numpy数组中大于指定阈值的数值为另一个值

Python在一定范围内替换数组中的元素

Python:替换数组中的 NaN 或 MEAN 而不是 -999 值[重复]

当步长大于1时,通过数组切片和numpy.diff替换python中的for循环

C# 如何高效替换一个字符串中的全部某字符?