假设我有以下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)
更新2:
您是否希望仅由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)]
(3,5)
和(5,3)
视为不同的事物,还是将它们视为相同的两个出现次数? - fountainhead[1,2,2]
生成了两个2元组(1,2)
(因为数字2
出现在不同的两列中),而你目前的解决方案将这两个2元组视为不同。这种区别重要吗? - fountainhead(a, b)
和(b, a)
视为不同的对会给我们更多的灵活性。 - MaxU - stand with Ukraine(a,b)
和(b,a)
之间的区别仅由a
和b
的源列引起,还是其他情况也可以?为了理解这个问题,请考虑三行[1,2,1]
、[3,1,2]
和[1,2,5]
。你认为这里的输出应该是什么?应该是哪些不同的二元组以及它们的频率? - fountainhead