【问题标题】:Count occurrences of unique arrays in array计算数组中唯一数组的出现次数
【发布时间】:2017-07-18 20:22:18
【问题描述】:

我有一个由各种热编码的 numpy 数组组成的 numpy 数组,例如;

x = np.array([[1, 0, 0], [0, 0, 1], [1, 0, 0]])

我想计算每个唯一的一个热向量的出现次数,

{[1, 0, 0]: 2, [0, 0, 1]: 1}

【问题讨论】:

  • 你试过什么? Stack Overflow 通常对没有尝试解决自己问题的问题皱眉。
  • 列表是不可散列的,您不能将其用作字典中的键。

标签: python numpy counter


【解决方案1】:

方法#1

似乎是使用numpy.unique(v1.13 和更新版本)的新功能的完美设置,它让我们可以沿着 NumPy 数组的轴工作 -

unq_rows, count = np.unique(x,axis=0, return_counts=1)
out = {tuple(i):j for i,j in zip(unq_rows,count)}

示例输出 -

In [289]: unq_rows
Out[289]: 
array([[0, 0, 1],
       [1, 0, 0]])

In [290]: count
Out[290]: array([1, 2])

In [291]: {tuple(i):j for i,j in zip(unq_rows,count)}
Out[291]: {(0, 0, 1): 1, (1, 0, 0): 2}

方法 #2

对于早于v1.13 的 NumPy 版本,我们可以利用输入数组是 one-hot 编码数组这一事实,就像这样 -

_, idx, count = np.unique(x.argmax(1), return_counts=1, return_index=1)
out = {tuple(i):j for i,j in zip(x[idx],count)} # x[idx] is unq_rows

【讨论】:

  • 注意axis是在numpy 1.13中添加的,所以以前的版本不能使用这个方法..
  • 方法 #2 可能更适用于 one-hot 数组的 np.eye 技巧。 u, count = np.unique(x.argmax(1), return_counts=1)i = np.eye(np.max(u))out = {i[u]:j for i, j in zip(u, count)}。这样你就不需要 return_index 或在你的循环中索引大的 one-hot 向量。 np.unique(...,axis)也万岁!
  • 然后我们可以通过@TemporalWolf 找到答案,并意识到当我们只能在第二个轴上求和时,我们完全在浪费时间做np.unique
  • @DanielF 谢谢!是的,可以使用np.eye(np.max(u)+1)。此外,沿第一个轴的summing 可以工作,如果我得到正确的话,只是掩盖zero 计数并将计数对应于它们各自的行的额外工作。
【解决方案2】:

您可以将数组转换为元组并使用 Counter:

import numpy as np
from collections import Counter
x = np.array([[1, 0, 0], [0, 0, 1], [1, 0, 0]])
Counter([tuple(a) for a in x])
# Counter({(1, 0, 0): 2, (0, 0, 1): 1})

【讨论】:

  • 这是唯一一个在 python 3 中使用字符串(或对象类型)的方法。
【解决方案3】:

给定数据格式的最快方法是:

x.sum(axis=0)

给出:

array([2, 0, 1])

第一个结果是第一个是热的数组的计数:

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

这利用了一次只能打开一个的事实,因此我们可以分解直接和。

如果您绝对需要将其扩展为相同的格式,可以通过以下方式进行转换:

sums = x.sum(axis=0)
{tuple(int(k == i) for k in range(len(sums))): e for i, e in enumerate(sums)}

或者,类似于 tarashypka:

{tuple(row): count for row, count in zip(np.eye(len(sums), dtype=np.int64), sums)}

产量:

{(1, 0, 0): 2, (0, 1, 0): 0, (0, 0, 1): 1}

【讨论】:

  • @EricDuminil 那编辑有帮助吗?如果不是,我再补充说明……sum的索引也是hot的索引。
  • 好的,知道了。我不知道“一个热”是什么意思。不错。
  • @EricDuminil 我假设 OP 正在谈论热线,但老实说我不知道​​。
  • @TemporalWolf 好吧,只是为了澄清这个问题 - 在给定的上下文中,每一行都是零,除了一个元素,称为 one-hot 编码向量。任务是计算相同向量的数量并将它们与向量一起分配。所以,例如对于x = np.array([[1, 0, 0, 0, 0], [0, 0, 0, 0, 1], [1, 0, 0, 0 , 0]]),我们将有:{(0, 0, 0, 0, 1): 1, (1, 0, 0, 0, 0): 2}
  • @Divakar 这对相同的信息进行编码,如果 OP 需要,可以扩展为该格式。我怀疑他没有,这是一个轻微的 XY 问题。
【解决方案4】:

这是另一个有趣的 sum 解决方案

>> {tuple(v): n for v, n in zip(np.eye(x.shape[1], dtype=int), np.sum(x, axis=0)) 
                if n > 0}
{(0, 0, 1): 1, (1, 0, 0): 2}

【讨论】:

  • 不错。我认为我们的答案正在趋同...x.sum(axis=0)。此外,[1]*len(x[0]) 使其适用于任何尺寸。
  • 如果有必要在字典中提供元组,我更喜欢你的版本。 np.diag() 非常适合这种用途。
【解决方案5】:

列表(包括 numpy 数组)是不可散列的,即它们不能是字典的键。所以你想要的精确输出,一个带有看起来像[1, 0, 0] 的键的字典在 Python 中是不可能的。为了解决这个问题,您需要将向量映射到元组。

from collections import Counter
import numpy as np

x = np.array([[1, 0, 0], [0, 0, 1], [1, 0, 0]])
counts = Counter(map(tuple, x))

这会让你得到:

In [12]: counts
Out[12]: Counter({(0, 0, 1): 1, (1, 0, 0): 2})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-01
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多