【问题标题】:Finding unique values in each row在每一行中查找唯一值
【发布时间】:2020-11-27 20:04:27
【问题描述】:

我有一个字符串大小为 2 的数组,并希望在每一行中获取唯一的字符串。

np.__version__
# '1.19.2'
arr = np.array([['Z7', 'Q4', 'Q4'], # 2 unique strings
                ['Q4', 'Z7', 'Q4'], # 2 unq strings
                ['Q4', 'Z7', 'Z7'], # 2 unq strings
                ['Z7', 'Z7', 'Q4'], # 2 unq strings
                ['D8', 'D8', 'L1'], # 2 unq strings
                ['L1', 'L1', 'D8']], dtype='<U2') # 2 unq strings

保证每一行都包含相同数量的唯一字符串,即每行都有相同数量的唯一字符串,在我的例子中是 2。

预期输出

array([['Q4', 'Z7'],
       ['Q4', 'Z7'],
       ['Q4', 'Z7'],
       ['Q4', 'Z7'],
       ['D8', 'L1'],
       ['D8', 'L1']], dtype='<U2')

在这里,每一行都已排序,但并非必须如此。两种方式都可以。

我的代码:

np.apply_along_axis(np.unique, 1, arr)

# array([['Q4', 'Z7'],
#        ['Q4', 'Z7'],
#        ['Q4', 'Z7'],
#        ['Q4', 'Z7'],
#        ['D8', 'L1'],
#        ['D8', 'L1']], dtype='<U2')

我认为在轴 1 上的 np.unique 会给出预期的结果,但是

np.unique(arr, axis=1)
# array([['Q4', 'Q4', 'Z7'],
#        ['Q4', 'Z7', 'Q4'],
#        ['Z7', 'Z7', 'Q4'],
#        ['Q4', 'Z7', 'Z7'],
#        ['L1', 'D8', 'D8'],
#        ['D8', 'L1', 'L1']], dtype='<U2')

我不明白到底发生了什么以及为什么它返回了这个确切的输出。

【问题讨论】:

    标签: python numpy numpy-ndarray


    【解决方案1】:

    这是因为 numpy.unique 将行或列子数组展平,然后返回唯一的行(axis = 0)或列(axis = 1),而不是唯一值本身。看看这个例子:

    a = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])
    np.unique(a, axis=0)
    

    输出是:

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

    b = np.array([[1, 1, 0], [1, 1, 0], [2, 2, 4]])
    np.unique(b, axis=1)
    

    输出是:

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

    在您的情况下,您需要每行本身的唯一值,因此应该像您已经实现的那样应用 along_axis 命令。 axis = 1 的作用不大,因为您的列都是唯一的,并且只显示一些排序。

    【讨论】:

    • 谢谢。现在我可以理解np.unique(arr, axis=1) 给出的输出了,有没有比np.apply_along_axis 更好的方法?
    • 我真的不知道你为什么想要一个不同的解决方案,因为它真的很好用?
    • np.apply_along_axis 很慢,它只是引擎盖下的 for-loop,没有矢量化。 More details here
    【解决方案2】:

    np.unique的文档,在axis参数的描述中, 包含以下语句:

    ...由给定轴索引的子数组将被展平,视为一维数组的元素

    所以如果你调用 np.unique,传递 axis=1,那么:

    • 每个都被展平(因为每列都包含“原子” 值,没有任何反应)。
    • 在结果列表中查找唯一元素 (列列表)。如果 2 列是一样的,那么只有 其中一个会被保留。
    • 结果可能以更改的顺序显示(这是 内部实现细节。

    解释一下为什么每个column(不是row):轴“1”实际上是“columns”。

    为了确认在这种情况下每个都是进程对象, 将源数组定义为:

    arr_2 = np.array([['Z7', 'Q4', 'Q4', 'Q4'],
                      ['Q4', 'Z7', 'Q4', 'Q4'],
                      ['Q4', 'Z7', 'Z7', 'Z7'],
                      ['Z7', 'Z7', 'Q4', 'Q4'],
                      ['D8', 'D8', 'L1', 'L1'],
                      ['L1', 'L1', 'D8', 'D8']])
    

    最后两列是一样的。

    当你执行np.unique(arr_2, axis=1)时,结果会 一样。最后两个完全相同, 所以其中一个已经被淘汰了。

    【讨论】:

    • 你的解释对我来说很重要。谢谢你。还有比np.apply_along_axis更好的办法吗?
    • 我认为,没有比 apply_along_axis 更好的方法了。
    猜你喜欢
    • 1970-01-01
    • 2021-05-24
    • 2023-01-19
    • 1970-01-01
    • 2016-10-07
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    相关资源
    最近更新 更多