构建分配矩阵 - Python
Construct an assignment matrix - Python
我有两个元素列表
a = [1,2,3,2,3,1,1,1,1,1]
b = [3,1,2,1,2,3,3,3,3,3]
并且我正在尝试唯一匹配 a 到 b 的元素,我的预期结果是这样的:
1: 3
2: 1
3: 2
所以我尝试构造一个赋值矩阵然后使用scipy.linear_sum_assignment
a = [1,2,3,2,3,1,1,1,1,1]
b = [3,1,2,1,2,3,3,3,3,3]
total_true = np.unique(a)
total_pred = np.unique(b)
matrix = np.zeros(shape=(len(total_pred),
len(total_true)
)
)
for n, i in enumerate(total_true):
for m, j in enumerate(total_pred):
matrix[n, m] = sum(1 for item in b if item==(i))
我预计矩阵是:
1 2 3
1 0 2 0
2 0 0 2
3 6 0 0
但是输出是:
[[2. 2. 2.]
[2. 2. 2.]
[6. 6. 6.]]
我在这里犯了什么错误?非常感谢
你甚至不需要 Pandas
处理这个。尝试使用 zip
和 dict
:
In [42]: a = [1,2,3,2,3,1,1,1,1,1]
...: b = [3,1,2,1,2,3,3,3,3,3]
...:
In [43]: c =zip(a,b)
In [44]: dict(c)
Out[44]: {1: 3, 2: 1, 3: 2}
UPDATE 正如 OP 所说,如果我们需要使用相同的键存储所有值,我们可以使用 defaultdict
:
In [58]: from collections import defaultdict
In [59]: d = defaultdict(list)
In [60]: for k,v in c:
...: d[k].append(v)
...:
In [61]: d
Out[61]: defaultdict(list, {1: [3, 3, 3, 3, 3, 3], 2: [1, 1], 3: [2, 2]})
这一行:
matrix[n, m] = sum(1 for item in b if item==(i))
计算i
在b
中出现的次数,并将结果保存到matrix[n, m]
。矩阵的每个单元格将包含 b
中 1 的数量(即 2)或 b
中 2 的数量(即 2)或 b
中 3 的数量(即6).请注意,此值完全独立于 j
,这意味着一行中的值将始终相同。
为了考虑j
,尝试将行替换为:
matrix[n, m] = sum(1 for x, y in zip(a, b) if (x, y) == (j, i))
以防您的预期输出,因为我们如何将矩阵指定为 a(i, j)
,其中 i
是行的索引,j
是列的索引。查看矩阵中的 a(3,1)
,结果为 6
,这意味着 (3,1) 组合匹配 6 次,其中 3 次来自 b,1 次来自 a。我们可以从 2 个列表中找到所有匹配项。
matches = [tuple([x, y]) for x,y in zip(b, a)]
然后我们可以找到特定组合有多少匹配,例如a(3, 1)。
result = matches.count((3,1))
我有两个元素列表
a = [1,2,3,2,3,1,1,1,1,1]
b = [3,1,2,1,2,3,3,3,3,3]
并且我正在尝试唯一匹配 a 到 b 的元素,我的预期结果是这样的:
1: 3
2: 1
3: 2
所以我尝试构造一个赋值矩阵然后使用scipy.linear_sum_assignment
a = [1,2,3,2,3,1,1,1,1,1]
b = [3,1,2,1,2,3,3,3,3,3]
total_true = np.unique(a)
total_pred = np.unique(b)
matrix = np.zeros(shape=(len(total_pred),
len(total_true)
)
)
for n, i in enumerate(total_true):
for m, j in enumerate(total_pred):
matrix[n, m] = sum(1 for item in b if item==(i))
我预计矩阵是:
1 2 3
1 0 2 0
2 0 0 2
3 6 0 0
但是输出是:
[[2. 2. 2.]
[2. 2. 2.]
[6. 6. 6.]]
我在这里犯了什么错误?非常感谢
你甚至不需要 Pandas
处理这个。尝试使用 zip
和 dict
:
In [42]: a = [1,2,3,2,3,1,1,1,1,1]
...: b = [3,1,2,1,2,3,3,3,3,3]
...:
In [43]: c =zip(a,b)
In [44]: dict(c)
Out[44]: {1: 3, 2: 1, 3: 2}
UPDATE 正如 OP 所说,如果我们需要使用相同的键存储所有值,我们可以使用 defaultdict
:
In [58]: from collections import defaultdict
In [59]: d = defaultdict(list)
In [60]: for k,v in c:
...: d[k].append(v)
...:
In [61]: d
Out[61]: defaultdict(list, {1: [3, 3, 3, 3, 3, 3], 2: [1, 1], 3: [2, 2]})
这一行:
matrix[n, m] = sum(1 for item in b if item==(i))
计算i
在b
中出现的次数,并将结果保存到matrix[n, m]
。矩阵的每个单元格将包含 b
中 1 的数量(即 2)或 b
中 2 的数量(即 2)或 b
中 3 的数量(即6).请注意,此值完全独立于 j
,这意味着一行中的值将始终相同。
为了考虑j
,尝试将行替换为:
matrix[n, m] = sum(1 for x, y in zip(a, b) if (x, y) == (j, i))
以防您的预期输出,因为我们如何将矩阵指定为 a(i, j)
,其中 i
是行的索引,j
是列的索引。查看矩阵中的 a(3,1)
,结果为 6
,这意味着 (3,1) 组合匹配 6 次,其中 3 次来自 b,1 次来自 a。我们可以从 2 个列表中找到所有匹配项。
matches = [tuple([x, y]) for x,y in zip(b, a)]
然后我们可以找到特定组合有多少匹配,例如a(3, 1)。
result = matches.count((3,1))