繁体   English   中英

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

[英]Python: Comparing all elements of two arrays and modifying 2nd array

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

我使用Numpy对'a'和'b'进行了比较,如下所示:

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)

我如何从这里开始获取'c'?

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

简单版

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. ])

尝试以更一般的方式更好地解释您的程序应该做什么。 只给出数组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]

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

使用np.isclose您已经创建了一个“最近”元素为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. ])

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

看来你想保留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)表示的元素的地方a是在bin1d(a,b)[False, True, True, False, False]

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

这是我能够获得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. ]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM