2016-04-09 28 views
1

关于Stack的第一个问题,大家好!用numpy数组和元组保留一个元素的快速方法

我有一个元组,有两个1D NP矩阵,从np.nonzero,例如:

(array([479, 479, 479, 480, 480, 480, 481, 481, 481, 482, 482, 482, 650, 650, 650, 651, 651, 651, 652, 652, 652, 653, 653, 653, 654, 654, 654, 708, 708, 708, 709, 709, 709, 710, 710, 710, 711, 711, 711, 712, 712, 712, 713, 713, 713], dtype=int64), array([ 859, 860, 861, 859, 860, 861, 859, 860, 861, 859, 860, 861, 1045, 1046, 1047, 1045, 1046, 1047, 1045, 1046, 1047, 1045, 1046, 1047, 1045, 1046, 1047, 1039, 1040, 1041, 1039, 1040, 1041, 1039, 1040, 1041, 1039, 1040, 1041, 1039, 1040, 1041, 1039, 1040, 1041], dtype=int64))

但在我的未来利用该元组将更大。我正在寻找最快的方法来保持元组第一列中每个元素(第一个元素)只有一个元素,并保留第二列中的第二个元素。此外,第一列进行排序

对于我的例子,我想这样的输出:

(array([479, 480, 481, 482, 650, 651, 652, 653, 654, 708, 709, 710, 711, 712], dtype=int64), array([861, 861, 861, 861, 1047, 1047, 1047, 1047, 1047, 1041, 1041, 1041, 1041, 1041],dtype=int64))

一个天真的解决办法是:

for k in range(len(nozero[0])-1): 
    i = nozero[0][k] 
    i2 = nozero[0][k+1] 
    j = nozero[1][k] 
    j2 = nozero[1][k+1] 

if i != i2: 
    x.append(i) 
    y.append(j) 

随意建议我任何事情这一点,但如果你有更好的想法来组织数据! (或者如果你想要更好的解释)。

非常感谢!

+0

保持其来自第二列坐标和数组(示出了[861,861,861,861,1047,1047,1047,1047,1047,1041,1041,1041,1041,1041],dtype = int64)。目前还不清楚你想用元组的第二个元素做什么。 BTW元组是不可变的,你不能改变它。所以你必须先将它转换为列表。 – Hun

+0

你应该避免for。正如你所说,如果你的元组在不久的将来会变得更大,那么对所有元素的循环将会被禁止。我会用numpy来完成任务的一部分 – Alejandro

+0

您应该使用更好的示例,或者您的数据总是如此规则。如果你总是有这样的规则模式,那么你可以用k = np.arange(0,len(nozeros [0]),3),然后,x = nozero [0] [ k]和y = nozero [1] [k]。 – Alejandro

回答

1

您可以在第一个阵列上使用np.diff查找所有第一次出现的掩码。然后使用掩码简单地切片每个阵列。

请注意,np.diff结果的数组大小比原始数据小一个,所以我们预先配置了一个1(数组中的第一个元素总是第一个)。

from numpy import array,int64 
import numpy as np 
arr1, arr2 = (array([479, 479, 479, 480, 480, 480, 481, 481, 481, 482, 482, 482, 650, 
     650, 650, 651, 651, 651, 652, 652, 652, 653, 653, 653, 654, 654, 
     654, 708, 708, 708, 709, 709, 709, 710, 710, 710, 711, 711, 711, 
     712, 712, 712, 713, 713, 713], dtype=int64), 
array([ 859, 860, 861, 859, 860, 861, 859, 860, 861, 859, 860, 
     861, 1045, 1046, 1047, 1045, 1046, 1047, 1045, 1046, 1047, 1045, 
     1046, 1047, 1045, 1046, 1047, 1039, 1040, 1041, 1039, 1040, 1041, 
     1039, 1040, 1041, 1039, 1040, 1041, 1039, 1040, 1041, 1039, 1040, 
     1041], dtype=int64)) 

first_occurences_mask = np.concatenate([[1], np.diff(arr1)], axis=0) > 0 
first_occurences_mask 
=> 
array([ True, False, False, True, False, False, True, False, False, 
     True, False, False, True, False, False, True, False, False, 
     True, False, False, True, False, False, True, False, False, 
     True, False, False, True, False, False, True, False, False, 
     True, False, False, True, False, False, True, False, False], dtype=bool) 

res1, res2 = (arr1[first_occurences_mask], arr2[first_occurences_mask]) 
res1, res2 
=> 
(array([479, 480, 481, 482, 650, 651, 652, 653, 654, 708, 709, 710, 711, 
     712, 713]), 
array([ 859, 859, 859, 859, 1045, 1045, 1045, 1045, 1045, 1039, 1039, 
     1039, 1039, 1039, 1039])) 

(顺便说一句,这是一个很好的第一个问题。您已经阅读规则和最佳实践,您发布之前,它显示了。)

EDIT(@alejandro ) - 时间比较

为了证明这种方法比@B更快。 M.,下面我做了这两个之间的比较:

from numpy import array,int64 
import numpy as np 
import time 

time1 = [] 
time2 = [] 

nelements = np.logspace(1,7) 

for i in nelements: 
    arr = np.random.randint(0,i, i) 

    start = time.time() 
    first_occurences_mask = np.concatenate([[1], np.diff(arr)], axis=0) > 0 
    stop = time.time() 
    time1.append(stop-start) 

    start = time.time() 
    np.unique(arr,return_index=True) 
    stop = time.time() 
    time2.append(stop-start) 

其给出以下结果:

enter image description here

该图清楚地表明,对于大阵列使用串连的加速是巨大的

+0

完美,这是您与B.M.之间最快的解决方案。非常感谢 ! – Wogle220

1

使用np.unique

In [1]: i,j = nozeros # your two arrays. 
In [3]: uniq,index,count=np.unique(i,return_index=True,return_counts=True) 

独特的元素OG我是uniq

In [4]: uniq 
Out[4]: 
array([479, 480, 481, 482, 650, 651, 652, 653, 654, 708, 709, 710, 711, 
     712, 713], dtype=int64) 

如果你想在j最后一个相应的元素在你的为例:

In [5]: j[index+count-1] 
Out[5]: 
array([ 861, 861, 861, 861, 1047, 1047, 1047, 1047, 1047, 1041, 1041, 
     1041, 1041, 1041, 1041], dtype=int64) 
+0

我想@Wogle220需要第二列中元素的值与第一列中的第一个元素相对应。如果是这样,你应该使用y [ind] – Alejandro

+0

不是'y [ind]'是什么OP后?此外,+1使用唯一和return_index – shx2

+0

它没有明确写出输出@ Wogle220想要的。 – Hun

相关问题