如何计算包含特定单词的文件?

Mel*_*kor 2 python counter dictionary frequency tf-idf

假设我有这样的字典:

docDict = {"alpha": ["a", "b", "c", "a", "b"], "bravo": ["b", "c", "d", "c", "d"]}
Run Code Online (Sandbox Code Playgroud)

而我想要做的就像计算"文档频率":假设每个字典项都是一个文档,我有一个特定的单词,那么有多少文档包含该单词?

我看过很多帖子告诉我如何计算频率,但是如果"a"在文档中出现两次"alpha",我只需要计数为1.所以"频率" "a"应该是1,"c"应该是2.

我知道我可以迭代整个文档字典,并在文档中找到单词时添加计数器.或者我可以首先使每个文档中的单词都是唯一的,然后组合所有文档并计算单词.

但我认为有更好的方法,更有效的方式.有任何想法吗?

顺便说一下,有什么方法可以保持字典的结构吗?在这个例子中,我想得到一个结果{"alpha": {'c': 2, 'b': 2, 'a': 1}, "bravo": {'c': 2, 'b': 2, 'd': 1}

更新

如果在这里我只有一个列表(类似的东西[["a", "b", "c", "a", "b"], ["b", "c", "d", "c", "d"]]),我怎么能得到像这样的结果列表[[1, 2, 2, 0], [0, 2, 2, 1]].

我不知道.关键是要扩展每个列表并确保术语的顺序.思考?

Ash*_*ary 6

我会用第二种方式使用collections.Counterset.

>>> from collections import Counter
>>> sum((Counter(set(x)) for x in docDict.itervalues()), Counter())
Counter({'c': 2, 'b': 2, 'a': 1, 'd': 1})
Run Code Online (Sandbox Code Playgroud)

更新1:

>>> c = sum((Counter(set(x)) for x in docDict.itervalues()), Counter())
>>> {k: {k1:c[k1] for k1 in set(v)} for k, v in docDict.iteritems()}
{'alpha': {'a': 1, 'c': 2, 'b': 2}, 'bravo': {'c': 2, 'b': 2, 'd': 1}}
Run Code Online (Sandbox Code Playgroud)

更新2 ::

如果性能是一个关注,那么请不要使用Countersum,这里另一种方式来做到这一点.请注意,与@ user2931409不同,我没有在内存中保留一组单词来获取它们的长度,因此这样的内存效率要高得多,但比它们的答案稍慢.

result = Counter()
for v in docDict.itervalues():
    result.update(set(v))
return result
Run Code Online (Sandbox Code Playgroud)

时间比较:

def func1():
    #http://stackoverflow.com/a/22787509/846892
    result = defaultdict(set)
    for k, vlist in docDict.items():
        for v in vlist:
            result[v].add(k)
    return dict(zip(result.keys(), map(lambda x:len(x), result.values())))

def func2():

    result = Counter()
    for v in docDict.itervalues():
        result.update(set(v))
    return result

In [94]: docDict = {''.join(random.choice(lis) for _ in xrange(8)): random.sample(lis, 25)
    ...:   for _ in xrange(70000)}

In [95]: %timeit func1(docDict)
1 loops, best of 3: 380 ms per loop

In [96]: %timeit func2(docDict)
1 loops, best of 3: 591 ms per loop

In [97]: docDict = {''.join(random.choice(lis) for _ in xrange(8)): random.sample(lis, 25)
    ...:   for _ in xrange(10**5)}

In [98]: %timeit func1(docDict)
1 loops, best of 3: 529 ms per loop

In [99]: %timeit func2(docDict)
1 loops, best of 3: 848 ms per loop

In [101]: func1(docDict) == func2(docDict)
Out[101]: True
Run Code Online (Sandbox Code Playgroud)