Python:比较两个数组的所有元素并修改第二个数组

时间:2016-02-28 12:25:16

标签: python arrays numpy

Python新手,并且一直在学习数组。我遇到了一个简单的问题,需要一个解决方案。我有两个数组:

a = [2.0, 5.1, 6.2, 7.9, 23.0]     # always increasing
b = [5.1, 5.5, 5.7, 6.2, 00.0]     # also always increasing

我希望得到的数组为:

c = [0.0, 5.1, 6.2, 0.0, 0.0]      # 5.5, 5.7, 00.0 from 'b' were dropped and rearranged such that position of equivalent elements as in 'a' are maintained

我比较了两个' a' &安培; ' B'使用Numpy,如:

y = np.isclose(a, b)
print y
# [False False False False False]

(或者,)我也试过这样的事情,这不是正确的方式(我认为):

c = np.zeros(len(a))
for i in range (len(a)):
    for j in range (len(a)):
        err = abs(a[i]-b[j])
        if err == 0.0 or err < abs(1):
            print (err, a[i], b[j], i, j)
        else:
            print (err, a[i], b[j], i, j)

如何从这里开始获取&#39; c&#39;?

5 个答案:

答案 0 :(得分:4)

即使阵列大小不同,这些解决方案也能正常工作。

简易版

c = []

for i in a:
    if any(np.isclose(i, b)):
        c.append(i)
    else:
        c.append(0.0)

Numpy版

aa = np.tile(a, (len(b), 1))
bb = np.tile(b, (len(a), 1))
cc = np.isclose(aa, bb.T)
np.any(cc, 0)
c = np.zeros(shape=a.shape)
result = np.where(np.any(cc, 0), a, c)

说明:

我将在这里进行矩阵比较。首先,将数组扩展为矩阵。交换长度,这会产生具有相同大小的一维矩阵:

aa = np.tile(a, (len(b), 1))
bb = np.tile(b, (len(a), 1))

他们看起来像这样:

# aa
array([[  2. ,   5.1,   6.2,   7.9,  23. ],
       [  2. ,   5.1,   6.2,   7.9,  23. ],
       [  2. ,   5.1,   6.2,   7.9,  23. ],
       [  2. ,   5.1,   6.2,   7.9,  23. ],
       [  2. ,   5.1,   6.2,   7.9,  23. ]])

# bb
array([[ 5.1,  5.5,  5.7,  6.2,  0. ],
       [ 5.1,  5.5,  5.7,  6.2,  0. ],
       [ 5.1,  5.5,  5.7,  6.2,  0. ],
       [ 5.1,  5.5,  5.7,  6.2,  0. ],
       [ 5.1,  5.5,  5.7,  6.2,  0. ]])

然后比较它们。请注意,bb是转置的:

cc = np.isclose(aa, bb.T)

你得到:

array([[False,  True, False, False, False],
       [False, False, False, False, False],
       [False, False, False, False, False],
       [False, False,  True, False, False],
       [False, False, False, False, False]], dtype=bool)

您可以按轴0聚合:

np.any(cc, 0)

返回

array([False,  True,  True, False, False], dtype=bool)

现在创建数组c:

c = np.zeros(shape=a.shape)

从a或c:

中选择适当的值
np.where(np.any(cc, 0), a, c)

结果:

array([ 0. ,  5.1,  6.2,  0. ,  0. ])

答案 1 :(得分:1)

尝试以更一般的方式更好地解释您的程序应该做什么。只给出数组a,b和c并不能告诉它应该做什么。就好像有人说“如果A = 5而B = 7,那就编写一个程序使C = 20”。

根据你的尝试,我猜测任务是“c的每个元素应该等于a的相应元素,如果它的值接近(差值为0.5或更小)与b中的相应值。如果没有,应该为零。“

另外,你真的需要使用numpy吗?尝试仅使用循环和列表方法。您还可以查看“生成器表达式和列表推导”

最后,你的标题是“(...)并修改第二个数组”。不应该有一个名为c的第三个数组。结果应出现在数组b的修改版本中。

编辑:如果规范是真的这个,那么代码可能是

a = [2.0, 5.1, 6.2, 7.9, 23.0]
b = [5.1, 5.5, 5.7, 6.2, 0.0]
c = []
for x,y in zip(a,b): c.append( x if abs(x-y)<=0.5 else 0.0 )
print c

其中给出了以下答案

[0.0, 5.1, 6.2, 0.0, 0.0]
顺便说一句,如果这是一个课程,你可能仍然会因为不遵守规范(“......并修改第二个数组”)而得分不好。

答案 2 :(得分:1)

使用np.isclose,您已经创建了一个数组,其中&#34;最接近&#34;元素是True。因此,您可以使用此结果将所有其他元素设置为零。

import numpy as np
a = np.array([2.0, 5.1, 6.2, 7.9, 23.0])     # always increasing
b = np.array([5.1, 5.5, 5.7, 6.2, 00.0])     # also always increasing
a[~np.isclose(a,b, atol=0.5)] = 0
a

这会返回array([ 0. , 5.1, 6.2, 0. , 0. ])

但请注意,您要设置所有不接近的元素,因此您需要反转(~)结果。

答案 3 :(得分:1)

您似乎希望保留a中同样位于b的元素。

纯线性时间python解决方案:

c=zeros_like(a)

j=0
n=len(c)
for i in range(n):
    while j<n and b[j]<a[i]-.1 : j+=1
    if j==n : break
    if abs(a[i]-b[j])<.1 : c[i]=a[i]

完全匹配的numpy解决方案:

a*in1d(a,b)

in1d(a,b)表示ab的{​​{1}}元素的位置:in1d(a,b)[False, True, True, False, False]

由于True1False0a*in1d(a,b)[ 0., 5.1, 6.2, 0. , 0. ]。由于in1dab进行排序,因此它是一种复杂的算法,但速度通常更快。如果需要近似相等,则解决方案可以首先对数组进行舍入(np.round(a,1)

答案 4 :(得分:0)

这是我能够获得c所需安排的替代方式。

import numpy as np

a = [2.0, 5.1, 6.2, 7.9, 23.0]  # always increasing
b = [5.1, 5.5, 5.7, 6.2, 00.0]  # also always increasing
c = np.zeros(len(a))

for i in range (len(a)):
    for j in range (len(a)):
        err = abs(a[i]-b[j])
        if err == 0.0 or err < abs(0.1):
            c[i] = b[j]

print c
#[ 0.   5.1  6.2  0.   0. ]