在Python中无法应用在numpy.darray中查找唯一行的方法

3
我想在numpy.ndarray中仅选择唯一的行(变量名为cluster)。当我像这样明确定义这个变量时:
cluster=np.array([[0.157,-0.4778],[0.157,-0.4778],[0.157,-0.4778],[-0.06156924,-0.21786049],[-0.06156924,-0.21786049],[0.02,-0.35]])

它按照预期工作:

[[ 0.157      -0.4778    ]
 [-0.06156924 -0.21786049]
 [ 0.02       -0.35      ]]

但不幸的是,这个变量cluster是一个更大的数组(xtrans)的一部分。因此,只能通过数组切片来定义它:

splitted_clusters=[0,1,4,5,10]

cluster=xtrans[splitted_clusters]

这些函数和数据类型都是相同的。

但是!!!在后一种情况下,它的行为非常奇怪:它可能会添加相同的行,也可能不会添加。结果就是我会得到像这样的东西:

    [[ 0.157      -0.4778    ]
     [ 0.157      -0.4778    ]
     [-0.06156924 -0.21786049]
     [ 0.02       -0.35      ]]

在我的实际例子中,使用一个44*2的数组时,它添加了22行相同的行,但错过了其中的23行(方案也非常奇怪:它添加了索引为0、1、2、4、9、11、12、18等的行)。但是添加的相同行数目不同。 而且它只应该添加这44行中的第一行。
至于选择唯一行的方法,我首先使用了来自此线程Find unique rows in numpy.array的方法。
b =np.ascontiguousarray(cluster).view(np.dtype((np.void, cluster.dtype.itemsize * cluster.shape[1])))
_, idx = np.unique(b, return_index=True)
unique_cl = cluster[idx]

然后我尝试了我的代码来检查:
unique_cl=np.array([0,0])
for i in range(cluster.shape[0]):
    if i==0:
        unique_cl=np.vstack([cluster[i,:]])
    elif cluster[i,:].tolist() not in unique_cl.tolist():
        unique_cl=np.vstack([unique_cl,cluster[i,:]]) 

结果是相同的,我真的不知道为什么。 如果有任何帮助/建议/建议/想法,我将非常感激。
问题出在浮点数上。当我将数组的值舍入到小数点后7位时,一切都按预期工作。感谢Eelco Hoogendoorn提出这个想法。

“b”是相同的吗?看起来“b”是相同的数据,但每一行被视为一个16字节的“void”元素。这使得“unique”可以进行其扁平化排序和选择。 - hpaulj
@hpaulj 我想是的,因为这段代码中没有其他的 b。它也是 'numpy.ndarray' 类型,但是当我尝试打印它时,我看到了奇怪的符号,我不知道如何编码/解码它们: [��|гY�? 9��v���? � h"lx�? @ ��|гY�? 9��v���? � h"lx�? ��|гY�? 9��v���? � h"lx�? �K7�A�? 9��v���? F����x�? ��|гY�? 9��v���? � h"lx�? @ ��|гY�? 9��v���? � h"lx�? ��|гY�? 9��v���? � h"lx�? @ @ @]` - Nataly
xtrans[splitted_clusters] 生成的 b 的形状和数据类型是什么?如果没有提供 xtrans 的样本或者如何转换以产生新的 b 的想法,我们无法调试您的问题。 - hpaulj
1
这可能是浮点精度问题吗?即,打印时浮点数看起来相同,但实际上不是按位相同的吗?尝试使用np.round并查看是否有所不同。 - Eelco Hoogendoorn
1
尝试对一般浮点值执行相等测试是棘手的。尝试对您认为相同的任意两行使用 xtrans[i,:]==xtrans[j,:]。或查看 xtrans[i,:]-xtrans[j,:]。这些行可能并不像您想象的那样独特。 - hpaulj
@EelcoHoogendoorn谢谢你,你说得对。现在它完美地工作了!!! - Nataly
3个回答

2
你可以通过将列表 list 转换为集合 set 来完成它。
 aList = [[ 0.157, -0.4778], [ 0.157, -0.4778],[-0.06156924,
 -0.21786049], [ 0.02, -0.35]]

将列表中的列表转换为元组列表,否则您将无法从中创建集合或字典set构造函数将为您完成其余工作:set([tuple(a) for a in aList])
set([(-0.06156924, -0.21786049), (0.02, -0.35), (0.157, -0.4778)])

然后,当然,您可以将其转换回二维“list”。 - Rudziankoŭ
谢谢您提供的这个想法,但我需要保存数组的原始索引。例如,在我问题中的第一段代码中,索引在变量“idx”中。 - Nataly

1

numpy_indexed包(免责声明:我是它的作者)以与您发布的解决方案类似的方式实现了此类功能。但希望它的单元测试能证明其有用,并且事情能够正常运行...您可以在您的数据集上尝试一下,看看是否存在相同的问题?

import numpy_indexed as npi
npi.unique(cluster)
# try this as well, to see if fp representation has something to do with it
npi.unique(cluster.round(4))   

0
在numpy数组中查找唯一行的解决方案是:
In [13]: uniq_vals, counts = np.unique(cluster, axis=0, return_counts=True)

In [14]: uniq_vals
Out[14]:
array([[-0.06156924, -0.21786049],
       [ 0.02      , -0.35      ],
       [ 0.157     , -0.4778    ]])

In [15]: counts
Out[15]: array([2, 1, 3], dtype=int64)

选项return_counts允许您获取唯一行的计数。
此解决方案在在numpy.array中查找唯一行中有所解释。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接