我有一些(很多)二进制编码的矢量,如:
[0, 1, 0, 0, 1, 0] #But with many more elements each one
并且它们都存储在numpy(2D)数组中,如:
[
[0, 1, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 1],
[0, 1, 0, 0, 1, 0],
]
我想获得每个标签集的频率表。因此,在此示例中,频率表将为:
[2,1]
因为第一个标签集有两个外观而第二个标签只有一个。
换句话说,我想从Scipy实现itemfreq或从numpy实现histogram,但不是针对单个元素而是针对列表实现。
现在我实现了以下代码:
def get_label_set_freq_table(labels):
uniques = np.empty_like(labels)
freq_table = np.zeros(shape=labels.shape[0])
equal = False
for idx,row in enumerate(labels):
for lbl_idx,label_set in enumerate(uniques):
if np.array_equal(row,label_set):
equal = True
freq_table[lbl_idx] += 1
break
if not equal:
uniques[idx] = row
freq_table[idx] += 1
equal = False
return freq_table
标签二进制编码的向量。
效果很好,但是当矢量数量很大(> 58.000)并且每个元素中的元素数量也很大(> 8.000)时它非常低
如何以更有效的方式完成?
答案 0 :(得分:2)
我假设你的意思是只有1和0的数组。对于那些,我们可以使用二进制缩放将每行缩减为标量,然后使用np.unique
-
In [52]: a
Out[52]:
array([[0, 1, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 1],
[0, 1, 0, 0, 1, 0]])
In [53]: s = 2**np.arange(a.shape[1])
In [54]: a1D = a.dot(s)
In [55]: _, start, count = np.unique(a1D, return_index=1, return_counts=1)
In [56]: a[start]
Out[56]:
array([[0, 1, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 1]])
In [57]: count
Out[57]: array([2, 1])
这是一个普遍的 -
In [33]: unq_rows, freq = np.unique(a, axis=0, return_counts=1)
In [34]: unq_rows
Out[34]:
array([[0, 0, 1, 0, 0, 1],
[0, 1, 0, 0, 1, 0]])
In [35]: freq
Out[35]: array([1, 2])