Python比较标记化列表

2024-04-25 03:40:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要尽快解决这个问题,因为它将应用于一个巨大的数据集:

鉴于此主列表:

m=['abc','bcd','cde','def']

…以及此列表的参考列表:

r=[['abc','def'],['bcd','cde'],['abc','def','bcd']]

我想将r中的每个列表与主列表(m)进行比较,并生成一个新的列表列表。这个新对象将有一个1表示基于m的顺序的匹配项,0表示不匹配项。因此,新对象(列表列表)的列表长度将始终与m相同。 以下是基于上述m和r的预期:

[[1,0,0,1],[0,1,1,0],[1,1,0,1]]

因为r的第一个元素是['abc','def'],并且有一个匹配项 对于m的第一和第四个元素,结果就是[1,0,0,1]。你知道吗

到目前为止,我的方法是这样的(可能太慢了,缺少零):

output=[]
for i in r:
    output.append([1 for x in m if x in i])

导致:

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

提前谢谢!你知道吗


Tags: 数据对象方法in元素列表foroutput
3条回答

您可以使用这样的嵌套列表:

>>> m = ['abc','bcd','cde','def']
>>> r = [['abc','def'],['bcd','cde'],['abc','def','bcd']]
>>> [[1 if mx in rx else 0 for mx in m] for rx in r]
[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]]

此外,您可以使用int(...)缩短1 if ... else 0,并且可以将r的子列表转换为set,这样单个mx in rx的查找速度更快。你知道吗

>>> [[int(mx in rx) for mx in m] for rx in r]
[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]]
>>> [[int(mx in rx) for mx in m] for rx in map(set, r)]
[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]]

虽然int(...)1 if ... else 0短一点,但它似乎也慢一些,所以您可能不应该使用它。在重复查找之前将r的子列表转换为set应该可以加快较长列表的速度,但是对于非常短的示例列表,它实际上比简单的方法慢。你知道吗

>>> %timeit [[1 if mx in rx else 0 for mx in m] for rx in r]
100000 loops, best of 3: 4.74 µs per loop
>>> %timeit [[int(mx in rx) for mx in m] for rx in r]
100000 loops, best of 3: 8.07 µs per loop
>>> %timeit [[1 if mx in rx else 0 for mx in m] for rx in map(set, r)]
100000 loops, best of 3: 5.82 µs per loop

对于较长的列表,使用set会更快,正如预期的那样:

>>> m = [random.randint(1, 100) for _ in range(50)]
>>> r = [[random.randint(1,100) for _ in range(10)] for _ in range(20)]
>>> %timeit [[1 if mx in rx else 0 for mx in m] for rx in r]
1000 loops, best of 3: 412 µs per loop
>>> %timeit [[1 if mx in rx else 0 for mx in m] for rx in map(set, r)]
10000 loops, best of 3: 208 µs per loop

一种方法使用^{}和一个循环-

np.array([np.in1d(m,i) for i in r]).astype(int)

在显式循环中,它看起来像这样-

out = np.empty((len(r),len(m)),dtype=int)
for i,item in enumerate(r):
    out[i] = np.in1d(m,item)

我们可以使用dtype=bool来提高内存和性能。你知道吗

样本运行-

In [18]: m
Out[18]: ['abc', 'bcd', 'cde', 'def']

In [19]: r
Out[19]: [['abc', 'def'], ['bcd', 'cde'], ['abc', 'def', 'bcd']]

In [20]: np.array([np.in1d(m,i) for i in r]).astype(int)
Out[20]: 
array([[1, 0, 0, 1],
       [0, 1, 1, 0],
       [1, 1, 0, 1]])

如果r的列表长度相等,我们就可以使用完全矢量化的方法。你知道吗

你差点就到了。你知道吗

如果xi中,则要添加1;如果不是,则要为m中的每个x添加0。你知道吗

所以脚本看起来像:1 if x in i else 0作为条件,for x in m

output = [[1 if x in i else 0 for x in m] for i in r]
print(output)

结果与

[[1, 0, 0, 1], [0, 1, 1, 0], [1, 1, 0, 1]]

相关问题 更多 >