从numpy结构化数组中删除重复值

2024-09-28 17:30:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个结构化数组v,比如

^{1}$

通常,v会大得多,使用其他例程计算的'a1''a6'值。假设v

^{pr2}$

我需要从每个条目中删除重复项,并(可选地)对每个条目进行排序,这样,在对v进行操作之后,我有另一个类似于

[[(0, 1, 2) (0, 1, 2, 3) (0, 1, 3)]
 [(0, 1, 2, 3) (0, 1, 2, 3) (1, 3)]
 [(0, 1, 2, 3) (0, 1, 3) (0, 1, 3)]]

我的预感是numpy.unique,但我做不到。有什么想法吗?在


Tags: numpy排序a1条目数组例程结构化unique
2条回答

比如说:

v = np.array(
    [[(2, 0, 0, 0, 0, 1), (1, 0, 3, 2, 1, 2), (3, 1, 3, 0, 3, 1)],
     [(1, 2, 1, 1, 0, 3), (3, 0, 3, 2, 3, 1), (1, 3, 1, 1, 3, 3)],
     [(0, 2, 3, 3, 1, 1), (0, 1, 1, 1, 3, 0), (0, 3, 3, 3, 1, 0)]])


def uniqueify(obj):
    if isinstance(obj[0], np.ndarray):
        return np.array([uniqueify(e) for e in obj])
    else:
        return np.unique(obj)


v2 = uniqueify(v)
print(v2)

输出:

^{pr2}$

注意:参差不齐的数组可能很奇怪。如果您只需创建(python)数组列表(列表的列表),您的情况也差不多,例如:

def uniqueify(obj):
    if isinstance(obj[0], np.ndarray):
        return [uniqueify(e) for e in obj]
    else:
        return np.unique(obj)

这通常会产生相同的结果,但是使用python列表来包含numpy数组:

[[array([0, 1, 2]), array([0, 1, 2, 3]), array([0, 1, 3])], [array([0, 1, 2, 3]), array([0, 1, 2, 3]), array([1, 3])], [array([0, 1, 2, 3]), array([0, 1, 3]), array([0, 1, 3])]]

或手动格式化:

[[array([0, 1, 2]), array([0, 1, 2, 3]), array([0, 1, 3])], 
 [array([0, 1, 2, 3]), array([0, 1, 2, 3]), array([1, 3])], 
 [array([0, 1, 2, 3]), array([0, 1, 3]), array([0, 1, 3])]]

使用set可以:

In [111]: np.array([tuple(set(i)) for i in v.ravel().tolist()]).reshape(3,3)
Out[111]: 
array([[(0, 1, 2), (0, 1, 2, 3), (0, 1, 3)],
       [(0, 1, 2, 3), (0, 1, 2, 3), (1, 3)],
       [(0, 1, 2, 3), (0, 1, 3), (0, 1, 3)]], dtype=object)

我返回了一个二维元组数组(dtype对象)。我没有保存结构化数组数据类型。我也可以返回一个集合数组,或者一个集合列表。在

或者使用tolist嵌套元组列表

^{pr2}$

我不需要原始的tolist;对raveled数组进行迭代就足够了

In [115]: [set(i) for i in v.ravel()]
Out[115]: 
[{0, 1, 2},
 {0, 1, 2, 3},
 {0, 1, 3},
 {0, 1, 2, 3},
 {0, 1, 2, 3},
 {1, 3},
 {0, 1, 2, 3},
 {0, 1, 3},
 {0, 1, 3}]

unique给出了相同的结果;我不能做np.unique(i),因为它试图处理整个1元素结构的数组:

In [117]: [np.unique(i.tolist()) for i in v.ravel()]
Out[117]: 
[array([0, 1, 2]),
 array([0, 1, 2, 3]),
 array([0, 1, 3]),
 array([0, 1, 2, 3]),
 array([0, 1, 2, 3]),
 array([1, 3]),
 array([0, 1, 2, 3]),
 array([0, 1, 3]),
 array([0, 1, 3])]

======================

这会将其转换为三维阵列

在[134]:v1=v.view(np.D类型('(6,)i4')

In [135]: v1
Out[135]: 
array([[[2, 0, 0, 0, 0, 1],
        [1, 0, 3, 2, 1, 2],
        [3, 1, 3, 0, 3, 1]],

       [[1, 2, 1, 1, 0, 3],
        [3, 0, 3, 2, 3, 1],
        [1, 3, 1, 1, 3, 3]],

       [[0, 2, 3, 3, 1, 1],
        [0, 1, 1, 1, 3, 0],
        [0, 3, 3, 3, 1, 0]]])

不过,我不确定这是否有用。将unique应用于最后一个维度与结构化表单有相同的问题。在

In [137]: [np.unique(i) for i in v1.reshape(-1,6)]

在===================== 我在下面写的是一维结构化数组。这个例子是二维的,当然可以把它展平。在


我的第一个想法是将其转换为一个列表,并对每个元组应用set。它是一个结构化数组,因此v.tolist()将是元组的列表。在

在Dan发现的链接中,我的第一个建议就是:

https://stackoverflow.com/a/32381082/901925

(重点放在计数上,bincount解决方案在这里没有帮助。)。在

 [set(i) for i in v.tolist()]

你甚至不需要翻译,尽管我需要测试它。我不知道结构化记录是否可以作为set的参数。在

 [set(i) for i in v]

不管结果如何,结果都是不同长度的项目列表。它们是集合、列表还是数组并不重要。只有它们不会是结构化数组——除非我们花额外的精力来确定哪些字段是唯一的。在

由于字段都是相同的数据类型,因此很容易将其转换为二维数组。在

 v.view(int, 6)  # 6 fields

应该做到这一点(需要测试)。(更正,将其转换为纯int数组并不像我想象的那么容易)。在

np.unique应该和set一样工作;但是我怀疑set对于6个值(或任何其他合理数量的字段)更快。在

相关问题 更多 >