我有一个列表列表,如下所示。
mylist = [[5274919, ["report", "porcelain", "firing", "technic"]], [5274920, ["implantology", "dentistry"]], [52749, ["method", "recognition", "long", "standing", "root", "perforation", "molar"]], [5274923, ["exogenic", "endogenic", "cause", "tooth", "jaw", "anomaly", "method", "method", "standing"]]]
我还有以下概念列表。
myconcepts = ["method", "standing"]
我想看看myconcepts
中的每个概念在mylist
记录中有多少次。即;
"method" = 2 times in records (i.e. in `52749` and `5274923`)
"standing" = 2 times in records
我当前的代码如下。
mycounting = 0
for concept in myconcepts:
for item in mylist:
if concept in item[1]:
mycounting = mycounting + 1
print(mycounting)
但是,我目前的mylist
非常大,大约有500万条记录。 myconcepts
列表包含大约10000个概念。
在我当前的代码中,一个概念花了将近1分钟的时间才能获得count
,这很慢。
我想知道在python中最有效的方法吗?
出于测试目的,我将数据集的一小部分附加到了https://drive.google.com/file/d/1z6FsBtLyDZClod9hK8nK4syivZToa7ps/view?usp=sharing
中很高兴在需要时提供更多详细信息。
答案 0 :(得分:2)
您可以展平输入,然后使用collections.Counter
:
import collections
myconcepts = ["method", "standing"]
mylist = [[5274919, ["report", "porcelain", "firing", "technic"]], [5274920, ["implantology", "dentistry"]], [5274921, ["method", "recognition", "long", "standing", "root", "perforation", "molar"]], [5274923, ["exogenic", "endogenic", "cause", "tooth", "jaw", "anomaly", "method", "standing"]]]
def flatten(d):
for i in d:
yield from [i] if not isinstance(i, list) else flatten(i)
r = collections.Counter(flatten(mylist))
result = {i:r.get(i, 0) for i in myconcepts}
输出:
{'method': 2, 'standing': 2}
编辑:记录查找:
result = {i:sum(i in b for _, b in mylist) for i in myconcepts}
输出:
{'method': 2, 'standing': 2}
答案 1 :(得分:2)
https://www.geeksforgeeks.org/python-count-the-sublists-containing-given-element-in-a-list/的适应方法3
from itertools import chain
from collections import Counter
mylist = [[5274919, ["report", "porcelain", "firing", "technic"]], [5274920, ["implantology", "dentistry"]], [52749, ["method", "recognition", "long", "standing", "root", "perforation", "molar"]], [5274923, ["exogenic", "endogenic", "cause", "tooth", "jaw", "anomaly", "method", "method", "standing"]]]
myconcepts = ["method", "standing"]
def countList(lst, x):
" Counts number of times item x appears in sublists "
return Counter(chain.from_iterable(set(i[1]) for i in lst))[x]
# Use dictionary comprehension to apply countList to concept list
result = {x:countList(mylist, x) for x in myconcepts}
print(result) # {'method':2, 'standing':2}
*修订后的当前方法(仅计算一次)*
def count_occurences(lst):
" Number of counts of each item in all sublists "
return Counter(chain.from_iterable(set(i[1]) for i in lst))
cnts = count_occurences(mylist)
result = {x:cnts[x] for x in myconcepts}
print(result) # {'method':2, 'standing':2}
性能(使用Jupyter Notebook比较发布的方法)
结果显示此方法与Barmar发布的方法很接近(即36 vs 42 us)
对当前方法的改进将时间减少了大约一半(即从36 us减少到19 us)。对于更多的概念(即问题中有1000个以上的概念),这种改进应该更加重要。
但是,原始方法的速度更快,为2.55 us / loop。
方法当前方法
%timeit { x:countList(mylist, x) for x in myconcepts}
#10000 loops, best of 3: 36.6 µs per loop
Revised current method:
%%timeit
cnts = count_occurences(mylist)
result = {x:cnts[x] for x in myconcepts}
10000 loops, best of 3: 19.4 µs per loop
方法2(来自Barmar帖子)
%%timeit
r = collections.Counter(flatten(mylist))
{i:r.get(i, 0) for i in myconcepts}
# 10000 loops, best of 3: 42.7 µs per loop
方法3(原始方法)
%%timeit
result = {}
for concept in myconcepts:
mycounting = 0
for item in mylist:
if concept in item[1]:
mycounting = mycounting + 1
result[concept] = mycounting
# 100000 loops, best of 3: 2.55 µs per loop
答案 2 :(得分:1)
将概念列表更改为集合,以便搜索将为O(1)。然后,您可以使用交集来计算每组中的匹配项数。
import set
mylist = [
[5274919, {"report", "porcelain", "firing", "technic"}],
[5274920, {"implantology", "dentistry"}],
[52749, {"method", "recognition", "long", "standing", "root", "perforation", "molar"}],
[5274923, {"exogenic", "endogenic", "cause", "tooth", "jaw", "anomaly", "method", "method", "standing"}]
]
myconcepts = {"method", "standing"}
mycounting = 0
for item in mylist:
mycounting += len(set.intersection(myconcepts, item[1]))
print(mycounting)
如果要分别获取每个概念的计数,则需要循环myconcept
,然后使用in
运算符。您可以将结果放入字典中。
mycounting = {concept: sum(1 for l in mylist if concept in l[1]) for concept in myconcepts}
print(mycounting) // {'standing': 2, 'method': 2}
因为concept in l[1]
是O(1),所以它仍然比使用列表更有效。