计算二维Numpy数组中数字对频率的最有效方法

最大容量

假设我有以下2D数组:

import numpy as np

np.random.seed(123)
a = np.random.randint(1, 6, size=(5, 3))

产生:

In [371]: a
Out[371]:
array([[3, 5, 3],
       [2, 4, 3],
       [4, 2, 2],
       [1, 2, 2],
       [1, 1, 2]])

有没有一种比以下解决方案更有效的方法(Numpy,Pandas等)来计算所有数字对的频率

from collections import Counter
from itertools import combinations

def pair_freq(a, sort=False, sort_axis=-1):
    a = np.asarray(a)
    if sort:
        a = np.sort(a, axis=sort_axis)
    res = Counter()
    for row in a:
        res.update(combinations(row, 2))
    return res

res = pair_freq(a)

产生这样的东西:

In [38]: res
Out[38]:
Counter({(3, 5): 1,
         (3, 3): 1,
         (5, 3): 1,
         (2, 4): 1,
         (2, 3): 1,
         (4, 3): 1,
         (4, 2): 2,
         (2, 2): 2,
         (1, 2): 4,
         (1, 1): 1})

要么:

In [39]: res.most_common()
Out[39]:
[((1, 2), 4),
 ((4, 2), 2),
 ((2, 2), 2),
 ((3, 5), 1),
 ((3, 3), 1),
 ((5, 3), 1),
 ((2, 4), 1),
 ((2, 3), 1),
 ((4, 3), 1),
 ((1, 1), 1)]

PS生成的数据集看起来可能有所不同-例如,像多索引Pandas DataFrame或其他。

我试图增加a数组的维数,np.isin()与所有对组合的列表一起使用,但是我仍然无法摆脱循环。

更新:

(a)您是否只对2个数字的组合频率感兴趣(而不对3个数字的组合频率感兴趣)?

是的,我仅对成对组合(2个数字)感兴趣

(b)您是否想将(3,5)与(5,3)区别开来?还是想将它们视为同一事物的两次出现?

实际上,两种方法都很好-如果需要,我可以随时对数组进行排序:

a = np.sort(a, axis=1)

UPDATE2:

您是否希望仅由于a和b的源列,才发生(a,b)和(b,a)之间的区别?要了解这个问题,请考虑三行[[1,2,1], [3,1,2], [1,2,5]]您认为这里的输出应该是什么?不同的2元组应该是什么,频率应该是多少?

In [40]: a = np.array([[1,2,1],[3,1,2],[1,2,5]])

In [41]: a
Out[41]:
array([[1, 2, 1],
       [3, 1, 2],
       [1, 2, 5]])

我希望得到以下结果:

In [42]: pair_freq(a).most_common()
Out[42]:
[((1, 2), 3),
 ((1, 1), 1),
 ((2, 1), 1),
 ((3, 1), 1),
 ((3, 2), 1),
 ((1, 5), 1),
 ((2, 5), 1)]

因为它更灵活,所以我想将(a,b)和(b,a)视为同一对元素,我可以这样做:

In [43]: pair_freq(a, sort=True).most_common()
Out[43]: [((1, 2), 4), ((1, 1), 1), ((1, 3), 1), ((2, 3), 1), ((1, 5), 1), ((2, 5), 1)]
保罗·潘泽

如果您的元素不是太大,则非负整数bincount很快:

from collections import Counter
from itertools import combinations
import numpy as np

def pairs(a):
    M = a.max() + 1
    a = a.T
    return sum(np.bincount((M * a[j] + a[j+1:]).ravel(), None, M*M)
               for j in range(len(a) - 1)).reshape(M, M)

def pairs_F_3(a):
    M = a.max() + 1
    return (np.bincount(a[1:].ravel() + M*a[:2].ravel(), None, M*M) +
            np.bincount(a[2].ravel() + M*a[0].ravel(), None, M*M))

def pairs_F(a):
    M = a.max() + 1
    a = np.ascontiguousarray(a.T) # contiguous columns (rows after .T)
                                  # appear to be typically perform better
                                  # thanks @ning chen
    return sum(np.bincount((M * a[j] + a[j+1:]).ravel(), None, M*M)
               for j in range(len(a) - 1)).reshape(M, M)

def pairs_dict(a):
    p = pairs_F(a)
    # p is a 2D table with the frequency of (y, x) at position y, x
    y, x = np.where(p)
    c = p[y, x]
    return {(yi, xi): ci for yi, xi, ci in zip(y, x, c)}

def pair_freq(a, sort=False, sort_axis=-1):
    a = np.asarray(a)
    if sort:
        a = np.sort(a, axis=sort_axis)
    res = Counter()
    for row in a:
        res.update(combinations(row, 2))
    return res


from timeit import timeit
A = [np.random.randint(0, 1000, (1000, 120)),
     np.random.randint(0, 100, (100000, 12))]
for a in A:
    print('shape:', a.shape, 'range:', a.max() + 1)
    res2 = pairs_dict(a)
    res = pair_freq(a)
    print(f'results equal: {res==res2}')
    print('bincount', timeit(lambda:pairs(a), number=10)*100, 'ms')
    print('bc(F)   ', timeit(lambda:pairs_F(a), number=10)*100, 'ms')
    print('bc->dict', timeit(lambda:pairs_dict(a), number=10)*100, 'ms')
    print('Counter ', timeit(lambda:pair_freq(a), number=4)*250,'ms')

样品运行:

shape: (1000, 120) range: 1000
results equal: True
bincount 461.14772390574217 ms
bc(F)    435.3669326752424 ms
bc->dict 932.1215840056539 ms
Counter  3473.3258984051645 ms
shape: (100000, 12) range: 100
results equal: True
bincount 89.80463854968548 ms
bc(F)    43.449611216783524 ms
bc->dict 46.470773220062256 ms
Counter  1987.6734036952257 ms

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在二维numpy数组中计算False值的最有效(和pythonic)方法?

计算二维 numpy 数组频率的有效方法

numpy - 为二维数组中的每对行计算 f(v1,v2) 的最有效方法

在二维numpy数组中获取邻居的有效方法

从二维数组中查找最大元素和最大元素列表的最有效方法?

在 Python 中匹配二维坐标的最有效方法

有效地计算二维数组中每个数字的重复次数

二维numpy数组中带有索引的Pandas数据帧的有效子集

创建初始重复数据的二维字符串数组的最有效方法是什么?

计算二维数组中的所有数字

计算二维数组中的所有数字

检查二维python数组中每个值的有效方法

在 Java 中修剪二维数组的有效方法

在二维数组中查找相邻像元的有效方法

解决python中二维矩阵相关问题的最有效方法

生成一维数组的多个移位的二维数组的有效方法

封装二维数组中子数组的有效Numpy采样

在numpy数组中查找模式的最有效方法

有效地为二维 numpy 数组中的一组连续值查找索引

如何有效地散布一个numpy的二维数组

如何以有效的方式创建二维 numpy 数组的相应元素的元组

有效地找到两个二维numpy数组的行相交

如何通过id有效地求和和表示二维NumPy数组?

如何有效地填充 numpy 二维数组?

numpy:数组中唯一值的最有效频率计数

快速检查二维数组的有效索引

有效替换二维数组的行或列

在Python中返回具有给定id的二维列表行(的副本)的最有效(最快捷)方法是什么?

获取二维数组范围内所有元素的有效方法?