0

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

import numpy as np
v = np.zeros((3,3), [('a1', np.int),('a2', np.int), ('a3', np.int),  
    ('a4', np.int), ('a5', np.int), ('a6', np.int)])

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

>>> print v
    [[(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)]]

我需要从每个条目中删除重复项,并(可选)对每个条目进行排序,以便在操作 之后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,但我无法让它发挥作用。有任何想法吗?

4

2 回答 2

1

怎么样的东西:

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)

输出:

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

注意:锯齿状数组可能很奇怪。如果您简单地创建(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])]]
于 2016-04-23T01:18:56.717 回答
0

本次使用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 对象)。我没有保留结构化数组 dtypes。我也可以返回一个集合数组或集合列表。

或者使用tolist嵌套的元组列表

In [112]: _.tolist()
Out[112]: 
[[(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)]]

我不需要原件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])]

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

这会将其转换为 3d 数组

在 [134] 中:v1=v.view(np.dtype('(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)]

===================== 我在下面写的是一维结构化数组。示例是 2d。当然,它可以被展平,所有这些都适用。


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

沿着这条线的东西是我在丹发现的链接中的第一个建议:

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

(重点是计数;bincount解决方案在这里无济于事。)。

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

您甚至可能不需要翻译它,尽管我必须对其进行测试。我不知道结构化记录是否可以作为set.

 [set(i) for i in v]

无论如何,结果将是不同长度的项目列表。它们是集合、列表还是数组并不重要。只有它们不会是结构化数组——除非我们付出额外的努力来识别哪些字段是唯一的。

由于这些字段都是相同的 dtype,因此很容易将其转换为 2d 数组。

 v.view(int, 6)  # 6 fields

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

np.unique应该和set; 但是我怀疑set6 个值(或任何其他合理数量的字段)更快。

于 2016-04-23T02:48:45.930 回答