将numpy数组转换为映射到行的值的dict

时间:2018-05-22 19:29:21

标签: python arrays numpy dictionary scipy

考虑到我有一个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

3 个答案:

答案 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 次。此外,设置成员资格是恒定时间。