我有一组名为h_unique
的独特单词。我还有一个名为h_tokenized_doc
的文档的2D列表,其结构类似于:
[ ['hello', 'world', 'i', 'am'],
['hello', 'stackoverflow', 'i', 'am'],
['hello', 'world', 'i', 'am', 'mr'],
['hello', 'stackoverflow', 'i', 'am', 'pycahrm'] ]
和h_unique
as:
('hello', 'world', 'i', 'am', 'stackoverflow', 'mr', 'pycharm')
我想要的是在标记化文档列表中找到唯一单词的出现次数 到目前为止,我想出了这段代码,但这似乎非常慢。有没有有效的方法来做到这一点?
term_id = []
for term in h_unique:
print term
for doc_id, doc in enumerate(h_tokenized_doc):
term_id.append([doc_id for t in doc if t == term])
在我的情况下,我有一份7000个文档的文档列表,结构如下:
[ [doc1], [doc2], [doc3], ..... ]
答案 0 :(得分:2)
它会变慢,因为您为每个唯一的单词运行整个文档列表一次。为什么不尝试将唯一的单词存储在字典中并为每个找到的单词添加它?
unique_dict = {term: [] for term in h_unique}
for doc_id, doc in enumerate(h_tokenized_doc):
for term_id, term in enumerate(doc):
try:
# Not sure what structure you want to keep it in here...
# This stores a tuple of the doc, and position in that doc
unique_dict[term].append((doc_id, term_id))
except KeyError:
# If the term isn't in h_unique, don't do anything
pass
这只会贯穿所有文件一次。
从上面的示例中,unique_dict
将是:
{'pycharm': [], 'i': [(0, 2), (1, 2), (2, 2), (3, 2)], 'stackoverflow': [(1, 1), (3, 1)], 'am': [(0, 3), (1, 3), (2, 3), (3, 3)], 'mr': [(2, 4)], 'world': [(0, 1), (2, 1)], 'hello': [(0, 0), (1, 0), (2, 0), (3, 0)]}
(当然假设你的例子中的拼写错误'pycahrm'
是故意的)
答案 1 :(得分:1)
term_id.append([doc_id for t in doc if t == term])
这不会为每个匹配的字词附加一个doc_id
;它将追加doc_id
的潜在多个相同值的完整列表。当然你不是故意这样做的。
根据您的示例代码,term_id
最终结果如下:
[[0], [1], [2], [3], [0], [], [2], [], [0], [1], [2], [3], [0], [1], [2], [3], [], [1], [], [3], [], [], [2], [], [], [], [], []]
这真的是你的意图吗?
答案 2 :(得分:1)
如果我理解正确,并根据您对您所说的问题的评论
是的,因为单个术语可能出现在多个文档中,例如上面的例子,你好,结果是[0,1,2,3],对于世界来说,它是[0,2]
看起来你想要做的是:对于h_unique
列表中的每个单词(如上所述,应该是set
,或dict
中的键,两者都具有O(1)
的搜索访问权限,遍历h_tokenized_doc
变量中包含的所有列表,并找到该单词出现在哪些列表中的索引。
IF 实际上您想要做的事情,您可以执行以下操作:
#!/usr/bin/env python
h_tokenized_doc = [['hello', 'world', 'i', 'am'],
['hello', 'stackoverflow', 'i', 'am'],
['hello', 'world', 'i', 'am', 'mr'],
['hello', 'stackoverflow', 'i', 'am', 'pycahrm']]
h_unique = ['hello', 'world', 'i', 'am', 'stackoverflow', 'mr', 'pycharm']
# Initialize a dict with empty lists as the value and the items
# in h_unique the keys
results = {k: [] for k in h_unique}
for i, line in enumerate(h_tokenized_doc):
for k in results:
if k in line:
results[k].append(i)
print results
哪个输出:
{'pycharm': [], 'i': [0, 1, 2, 3], 'stackoverflow': [1, 3],
'am': [0, 1, 2, 3], 'mr': [2], 'world': [0, 2],
'hello': [0, 1, 2, 3]}
这个想法是使用h_unique
列表作为字典中的键(results = {k: [] for k in h_unique}
部分)。
词典中的键具有持续查找时间的优势,这对于if k in line:
部分非常有用(如果它是列表,in
将采用O(n)
)然后检查如果单词(键k
)出现在列表中。如果是,请将 list
中的 matrix
的索引附加到结果词典中。
虽然我不确定这是你想要达到的目的。
答案 3 :(得分:1)
您可以使用
优化代码以实现这一目的生成器词典用于持续查找时间,如前所述。生成器比for循环更快,因为生成值即时
In [75]: h_tokenized_doc = [ ['hello', 'world', 'i', 'am'],
...: ['hello', 'stackoverflow', 'i', 'am'],
...: ['hello', 'world', 'i', 'am', 'mr'],
...: ['hello', 'stackoverflow', 'i', 'am', 'pycahrm'] ]
In [76]: h_unique = ('hello', 'world', 'i', 'am', 'stackoverflow', 'mr', 'pycharm')
In [77]: term_id = {k: [] for k in h_unique}
In [78]: for term in h_unique:
...: term_id[term].extend(i for i in range(len(h_tokenized_doc)) if term in h_tokenized_doc[i])
产生输出
{'am': [0, 1, 2, 3],
'hello': [0, 1, 2, 3],
'i': [0, 1, 2, 3],
'mr': [2],
'pycharm': [],
'stackoverflow': [1, 3],
'world': [0, 2]}
更具描述性的解决方案是
In [79]: for term in h_unique:
...: term_id[term].extend([(i,h_tokenized_doc[i].index(term)) for i in range(len(h_tokenized_doc)) if term in h_tokenized_doc[i]])
In [80]: term_id
Out[80]:
{'am': [(0, 3), (1, 3), (2, 3), (3, 3)],
'hello': [(0, 0), (1, 0), (2, 0), (3, 0)],
'i': [(0, 2), (1, 2), (2, 2), (3, 2)],
'mr': [(2, 4)],
'pycharm': [],
'stackoverflow': [(1, 1), (3, 1)],
'world': [(0, 1), (2, 1)]}