考虑到我有一个2D numpy数组,其中每一行代表一个唯一的项目,行中的每一列代表一个分配给该项目的标签。例如,此实例中的10 x 25数组将代表10个项目,每个项目最多包含25个标签。
将此标签转换为dict(或其他适当的数据类型,如果可以按长度排序的奖励积分)将标签映射到出现该标签的行索引的最有效方法是什么?例如,dict[1]
将返回包含1
作为标签的行索引列表。
例如,
Given:
[1, 2, 3]
[1, 0, 0]
[1, 3, 0]
Result:
1: 0, 1, 2 # 1 occurs in rows 0, 1, 2
3: 0, 2 # 3 occurs in rows 0, 2
0: 1, 2 # 0 occurs in rows 1, 2 (0 is padding for lack of labels)
2: 0 # 2 occurs in row 0 only
答案 0 :(得分:4)
更新:按长度添加排序。
我们可以使用高级索引来创建由项目和标签索引的网格。
然后我们可以迭代列并使用flatnonzero
来获取项ID:
>>> ex = [[1, 2, 3],
... [1, 0, 0],
... [1, 3, 0]]
>>>
>>> m = len(ex)
>>> n = np.max(ex) + 1
>>> grid = np.zeros((m, n), int) # could also use a smaller dtype here
>>> grid[np.arange(m)[:, None], ex] = 1
>>> grid
array([[0, 1, 1, 1],
[1, 1, 0, 0],
[1, 1, 0, 1]])
>>> idx = np.argsort(np.count_nonzero(grid, 0))[::-1]
>>> dict(zip(idx, map(np.flatnonzero, grid.T[idx])))
{1: array([0, 1, 2]), 3: array([0, 2]), 0: array([1, 2]), 2: array([0])}
请注意,词典会记住其键的插入顺序。这是3.6中的实现细节,但将是3.7中的保证功能。
答案 1 :(得分:3)
您可以使用collections.defaultdict
,然后使用OrderedDict
按观察次数排序:
import numpy as np
from collections import defaultdict, OrderedDict
A = np.array([[1, 2, 3],
[1, 0, 0],
[1, 3, 0]])
d = defaultdict(list)
for idx, row in enumerate(A):
for i in set(row):
d[i].append(idx)
res = OrderedDict(sorted(d.items(), key=lambda x: len(x[1]), reverse=True))
print(res)
OrderedDict([(1, [0, 1, 2]),
(3, [0, 2]),
(0, [1, 2]),
(2, [0])])
答案 2 :(得分:1)
您可以定义一个{}
并遍历数组,随时添加值,如下所示:
def f(array):
table = {} # Initialize the dict
for rownumber, row in enumerate(array): # Goes through all of the rows, with associated numbering
for element in set(row): # Deduplicate to avoid duplicate row numbers
if element not in table: table[element] = [] # Initialize empty row list if this element is new
table[element].append(rownumber+1) # Add the current row number to the associated list of rows
return d
print(f([[1, 2, 3], [1, 0, 0], [1, 3, 0]]))
这种方法 O(N 2 )。这是因为set()是线性的并且被称为 N 次。此外,设置成员资格是恒定时间。