根据python矩阵中特定行中的值对列值进行计数

时间:2019-03-12 09:40:46

标签: python-3.x numpy

mat = [ [1,3,5,7], [1,2,5,7], [8,2,3,4] ]

我必须设计一个函数,该函数可以考虑参考行来计算具有相同值(每列)的行数。

每行的结果数组将是

row0 = [2,1,2,2]
row1 = [2,2,2,2]
row3 = [1,2,1,1]

矩阵垫的每一行都是用户,每一列都是用户在定义的时间单位中位置的标签。因此,我必须在每个定义的时间(即列)中统计有多少用户共享同一职位。

我尝试使用numpy count_nonzero函数,但它需要一个条件,即我无法在所有参考行中进行散布

3 个答案:

答案 0 :(得分:1)

一种简单的矢量化解决方案是使用

mat = np.array([
    [1,3,5,7],
    [1,2,5,7],
    [8,2,3,4]
])

tmp = mat + np.arange(mat.shape[1]) * np.max(mat)
np.bincount(tmp.ravel())[tmp]
# array([[2, 1, 2, 2],
#        [2, 2, 2, 2],
#        [1, 2, 1, 1]])

64x8640矩阵的时间:

# 4 ms ± 300 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

答案 1 :(得分:1)

这是一个使用`argsort的numpy解决方案。这可以处理非整数条目:

import numpy as np

def count_per_col(a):
    o = np.argsort(a, 0)
    ao = np.take_along_axis(a, o, 0)
    padded = np.ones((ao.shape[1], ao.shape[0]+1), int)
    padded[:, 1:-1] = np.diff(ao, axis=0).T
    i, j = np.where(padded)
    j = np.maximum(np.diff(j), 0)
    J = j.repeat(j)
    out = np.empty(a.shape, int)
    np.put_along_axis(out, o, J.reshape(out.shape[::-1]).T, 0)
    return out

mat = np.array([[1,3,5,7], [1,2,5,7], [8,2,3,4]])

count_per_col(mat)
# array([[2, 1, 2, 2],
#        [2, 2, 2, 2],
#        [1, 2, 1, 1]])

多快?

from timeit import timeit

large = np.random.randint(0, 100, (100, 10000))
large = np.random.random(100)[large]

timeit(lambda: count_per_col(large), number=10)/10
# 0.1332556433044374

答案 2 :(得分:0)

有一个简单的解决方案:1)计算每列中的元素数量,2)使用该数量来构建另一个列表。

from collections import Counter

mat = [[1,3,5,7], [1,2,5,7], [8,2,3,4]]
col_counts = [Counter(col) for col in zip(*mat)]
results = [[count[cell] for cell, count in zip(row, col_counts)] for row in mat]

结果是:

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

请注意,在第一行[1,3,5,7]中,元素3对应于1而不是零,因为第二列{{1}中正好有一个3 }。

一种更轻巧的解决方案(一次仅使用一个计数器),我还逐行详细介绍了转换,以便于理解:

[3, 2, 2]

如果需要列表,则可以调用def row_count(mat): def row_transform(row): count = Counter(row) return [count[e] for e in row] matT = zip(*mat) matT_count = map(row_transform, matT) return zip(*matT_count) ,如果只需要遍历行,可以执行list(row_count(mat)),这样可以节省更多的内存(一次仅实例化一行) )。