2016-02-28 73 views
2

Python新手,并且一直在学习数组。我坚持一个足够简单的问题,需要一个解决方案。我有两个阵列: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 

我比较两者 '一' & '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) 

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

+1

尝试'y = np.isclose(a,b,atol = 0.05)'。 – Norman

+0

它不影响结果。把'atol = 0.5'给出'[False True False False]',这是'c'bool明智的。 – rNov

+0

我是否简单地将'a'的元素值复制到'True'值的位置?还是有更好的方法呢? – rNov

回答

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) 

,你会得到:

np.any(cc, 0) 

返回

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

现在创建:

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汇总此数组c:

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

并选择合适的值,无论是从一个或c:

np.where(np.any(cc, 0), a, c) 

而结果:

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

我认为这是OP想要的。但他现在添加了一条评论,说在'b'数组末尾可能存在一些必须忽略的垃圾值。所以在使用之前需要修改该数组,或者修改算法。 (适用于所有当前的答案,我认为。) – Norman

+0

是的,我已经添加了关于这个假设的评论。如有必要,余数可以是np.append。 – hruske

+0

非常详细的解释我必须说。唯一的问题是,如果使用numpy生成零(例如)'c'的空矩阵,将不会'np.append'抛出错误,而不是使用'c [i] = b [j]'。 – rNov

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] 

顺便说一句,如果这是一个过程,你仍然可能因为不遵循规范而导致不好的成绩(“......并修改第二个数组”)。

+0

你猜对了任务。我试着交替使用循环代替Numpy(请参阅第二段代码)。修改第二个数组是我需要做的,但我会解决第三个数组'''因为它有助于保持简单的暂时。 – rNov

+0

提示:如果您是以python开头,您应该坚持使用基本语言(即python文档中的“语言参考”和“库参考”)。不要尝试使用外部库(例如Numpy)。 –

+0

这不是一个顺便说一句,我是一个数据科学爱好者,在处理不同的数据集时遇到了这个问题。数组实际上代表了一个更大的数据集的列。 – rNov

1

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

但是请注意,您希望设置所有未关闭的元素,因此您需要反转(~)结果。

1

看来你想保留a也是b的元素。

纯线性时间蟒溶液:

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是在b元件的地方:in1d(a,b)[False, True, True, False, False]

由于True1False0a*in1d(a,b)[ 0., 5.1, 6.2, 0. , 0. ]。由于in1d分类为ab,这是一个复杂的算法,但通常更快。如果需要近似相等,则解决方案可以先舍入阵列(np.round(a,1)

+0

我的解决方案与您的解决方案非常相似,只使用嵌套for循环 – rNov

+0

是的,但它是一种二次算法,它不使用数组排序的事实。在大数组上效率不高。 –

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. ] 
+0

谢谢。现在你的目标更清晰了。我在帖子中给出了更有效的解决方案。 –

+0

在'if'语句中,'abs(0.1)'可以在没有'abs'函数的情况下被写入(abs(0.1)为0.1)。同样,如果'err == 0.0',那也意味着'err <0.1',所以第一个条件是多余的。你可以写'如果错误<0.1:'。 –

+0

在这种情况下,abs(0.1)'是多余的,但是当值足够接近时,在某些情况下'err'可能是负数。因此需要'err == 0'和'err rNov

相关问题