Python中的高效阵列替换

时间:2011-09-08 18:35:00

标签: python arrays numpy replace

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

答案 0 :(得分:4)

我认为提取所有好的值会更快,然后在需要时使用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和{{1 }}

然后列表理解的核心是“三元if”语句,如下所示:

x

如果a if flag else b 值为true,则上面将返回值a,否则返回flag。列表理解中的一个是:

b

这实现了我们的规则。