根据其值更改numpy数组的各个元素

时间:2019-02-27 12:16:17

标签: python arrays numpy iteration numpy-ndarray

我正在尝试遍历numpy数组的每个元素,并以半随机方式更改其值。这样做的原因是,我将该方法应用于不同的数组:我希望更改它们,但我不希望它们以相同的方式更改。

这是我到目前为止尝试过的:

with np.nditer(smatrix, op_flags=['readwrite']) as it:
    for element in it:
        if element < 0:
            element = element - uniform(0.1,0.2)
        if 0 <= element < 0.05:
            element = uniform(0.15,0.3)
        elif 0.05 <= element < 1:
            element = 0
        elif 1 == element:
            element = 1

另一种可能性:

for element in np.nditer(smatrix, op_flags=['readwrite']):
    if element < 0:
        element = element - uniform(0.1,0.2)
    if 0 <= element < 0.05:
        element = uniform(0.15,0.3)
    elif 0.05 <= element < 1:
        element = 0
    elif 1 == element:
        element = 1

但是,结果数组看起来与初始数组完全相同...

我对编程还比较陌生,并且在这个问题上停留了很长时间。如果有人能给我一些解决方法的提示,最好是简短的解释,那将是非常棒的。谢谢!!

2 个答案:

答案 0 :(得分:0)

如果要将变换应​​用于numpy.array的每个单元格,那么numpy.vectorize是正确的工具。 首先,您需要使用函数,该函数将使用单个单元格的内容作为输入,该函数本身将被馈送到vectorize且需要return的期望值,请参见代码:

import numpy as np
import random
def f(x):
    if x < 0:
        return x-random.uniform(0.1,0.2)
    if 0 <= x < 0.05:
        return random.uniform(0.15,0.3)
    if 0.05 <= x < 1:
        return 0.0
    if x == 1:
        return 1.0
    return x
vf = np.vectorize(f)

data = np.array([-4.3,0.03,0.9,1.0,1.9])
altered_data = vf(data)

输出(由于部分随机,可能与您有所不同):

[-4.48922564  0.19609667  0.          1.          1.9       ]

您可以检查它对所有值的作用。请注意,我添加了“对元素不执行操作”(return x)作为安全措施,以防元素大于1

有关numpy.vectorize的更多信息,请阅读documentation

编辑:已修正在评论中报告的问题,问题是f有时return编辑了int,有时float,而它应该始终return {{ 1}}。

答案 1 :(得分:0)

我认为nditer需要更强有力的免责声明。对于初学者来说,它不是一个很好的迭代工具。使用权利很难,而且速度不是特别快。这个Python版本确实是在编译代码中使用它的踏脚石,如cython主页末尾的nditer示例所示:

https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html

可以使用更快的方法进行这种数组计算,但是我将尝试解释为什么您的nditer无法正常工作。

问题在于基本的Python迭代。像这样的循环:

alist = [0,0,0]
for element in alist:
    element = 1

alist未修改。 element=1只是重新分配了element变量,但没有修改迭代变量本身。相反,您可以对element本身进行突变。

对于nditer,迭代变量本身就是ndarray,并且是可变的:

In [69]: smatrix = np.zeros((2,2),int)                                          
In [70]: with np.nditer(smatrix, op_flags=['readwrite']) as it: 
    ...:     for element in it: 
    ...:         print(element, type(element)) 
    ...:         element[...] = 1 
    ...:                                                                        
0 <class 'numpy.ndarray'>
0 <class 'numpy.ndarray'>
0 <class 'numpy.ndarray'>
0 <class 'numpy.ndarray'>
In [71]: smatrix                                                                
Out[71]: 
array([[1, 1],
       [1, 1]])

如果不清楚,请仔细查看https://docs.scipy.org/doc/numpy/reference/generated/numpy.nditer.html中的示例。注意使用out参数和类似x[:] = [-1, -2, -3]的表达式。

如果这种关于变异变量的说法令人困惑,则很好地表明nditer在这一点上太先进了。