python - 从两个列表(源列表和标签列表)有效地生成唯一的正负三元组
问题描述
我对 python 很陌生,我想从两个列表中生成所有唯一的三元组。所以,我有两个这样的列表:
source_list=[1,2,3,4,5,6,7,8..] # size N
labels_list=[1,1,0,2,1,3,6..] # size N
我想要三胞胎形式:
<anchor> <postive> <negative>
其中,<anchor>
可以是 中的任何元素source_list
,postive
表示该元素应该来自与锚点相同的标签(因此,1,2 和 1,5 可以被视为三元组中的正对)并且negative'
s 表示它们应该来自不同的标签(因此,1,3 和 1,4 将被视为三元组的负对)。因此,正确三元组的一些示例是:
1, 2, 3
1, 2, 4
1, 2, 6
从一开始这似乎是一个N choose k
问题,但我不知道如何以最小的计算成本来解决这个问题,而不是在 python 中对每个元素进行循环。
解决方案
numpy
可能有更快的方法来做到这一点,但我们可以用and很好地解决它itertools
。首先,对于每个唯一的标签k,我们需要划分source_list
为对应于标签k的条目(“正”部分)和不对应的条目(“负”部分)。
>>> source_list = [1,2,3,4,5,6,7,8] #... size N
>>> labels_list = [1,1,0,2,1,3,6,2] #... size N
>>> for key in set(labels_list):
... positive = [s for i,s in enumerate(source_list) if labels_list[i] == key]
... negative = [s for i,s in enumerate(source_list) if labels_list[i] != key]
... print(key, positive, negative)
...
0 [3] [1, 2, 4, 5, 6, 7, 8]
1 [1, 2, 5] [3, 4, 6, 7, 8]
2 [4, 8] [1, 2, 3, 5, 6, 7]
3 [6] [1, 2, 3, 4, 5, 7, 8]
6 [7] [1, 2, 3, 4, 5, 6, 8]
我们可以使用 NumPy 和 masking 稍微加快速度,这基本上可以让我们避免两次执行列表推导。
>>> import numpy as np
>>> source_array = np.array([1,2,3,4,5,6,7,8])
>>> labels_array = np.array([1,1,0,2,1,3,6,2])
>>> for key in np.unique(labels_array):
... mask = (labels_array == key)
... positive = source_array[mask]
... negative = source_array[~mask] # "not" mask
... print(key, positive, negative)
...
0 [3] [1 2 4 5 6 7 8]
1 [1 2 5] [3 4 6 7 8]
2 [4 8] [1 2 3 5 6 7]
3 [6] [1 2 3 4 5 7 8]
6 [7] [1 2 3 4 5 6 8]
旁注:如果<anchor>
和<positive>
不允许代表相同的条目sources_list
,那么我们需要每个正组至少有两个成员。这可能会发生在您的实际数据中,但对于此演示,我们将仅跳过带有单一阳性的案例。
现在来了itertools
。我们想要来自肯定列表的 2 个条目的所有唯一排列,以及来自否定列表的另一个条目。由于结果必须是唯一的,我们可以稍微降低复杂性,从每个正面和负面列表中删除重复项。
>>> import itertools
>>> import numpy as np
>>> source_array = np.array([1,2,3,4,5,6,7,8])
>>> labels_array = np.array([1,1,0,2,1,3,6,2])
>>> for key in np.unique(labels_array):
... mask = (labels_array == key)
... positive = np.unique(source_array[mask]) # No duplicates
... if len(positive) < 2: # Skip singleton positives
... continue
... negative = np.unique(source_array[~mask]) # No duplicates
... print(key, positive, negative)
... for ((a,b),c) in itertools.product(itertools.permutations(positive, 2),
... negative):
... print(a,b,c)
... print()
输出:
1 [1 2 5] [3 4 6 7 8]
1 2 3
1 2 4
1 2 6
1 2 7
1 2 8
1 5 3
1 5 4
1 5 6
1 5 7
1 5 8
2 1 3
2 1 4
2 1 6
2 1 7
2 1 8
2 5 3
2 5 4
2 5 6
2 5 7
2 5 8
5 1 3
5 1 4
5 1 6
5 1 7
5 1 8
5 2 3
5 2 4
5 2 6
5 2 7
5 2 8
2 [4 8] [1 2 3 5 6 7]
4 8 1
4 8 2
4 8 3
4 8 5
4 8 6
4 8 7
8 4 1
8 4 2
8 4 3
8 4 5
8 4 6
8 4 7
推荐阅读
- javascript - Hiding a div automatically when other related divs are also hidden
- python - How can I get get all possible paths from any tree using python function that takes dataframe?
- git - 如何使用 git 跟踪子文件夹?
- pdf - 如何使用图像的 tesseract 输出从另一个图像创建可搜索的 pdf
- java - 有什么方法可以快速模拟@SpyBean 的所有方法
- android - 有没有办法将 OBS 虚拟相机流式传输到 Android 模拟器?
- c++ - C++ BucketList 类初始化
- mysql - 连接一个表中的两列并查找它没有出现在另一个表中的位置 mysql
- if-statement - 当某些东西必须位于两条线之间时会是什么情况
- pdf - 为什么将分页报表导出为 pdf 时文本会被截断?