为文件中的每个单词创建一个字典,并计算其后的单词的频率

时间:2017-06-23 20:22:15

标签: python dictionary nltk counter n-gram

我正在努力解决一个棘手的问题并且迷路了。

这是我应该做的事情:

INPUT: file
OUTPUT: dictionary

Return a dictionary whose keys are all the words in the file (broken by
whitespace). The value for each word is a dictionary containing each word
that can follow the key and a count for the number of times it follows it.

You should lowercase everything.
Use strip and string.punctuation to strip the punctuation from the words.

Example:
>>> #example.txt is a file containing: "The cat chased the dog."
>>> with open('../data/example.txt') as f:
...     word_counts(f)
{'the': {'dog': 1, 'cat': 1}, 'chased': {'the': 1}, 'cat': {'chased': 1}}

到目前为止,我所有人都试图至少提出正确的词语:

def word_counts(f):
    i = 0
    orgwordlist = f.split()
    for word in orgwordlist:
        if i<len(orgwordlist)-1:
            print orgwordlist[i]
            print orgwordlist[i+1]

with open('../data/example.txt') as f:
    word_counts(f)

我认为我需要以某种方式使用.count方法并最终将一些词典压缩在一起,但我不确定如何计算每个第一个词的第二个词。

我知道我无法解决问题,但试图一步一步。任何帮助都表示赞赏,即使是指向正确方向的提示也是如此。

5 个答案:

答案 0 :(得分:7)

我们可以在两次传递中解决这个问题

  1. 在第一遍中,我们构造一个Counter并使用zip(..)计算两个连续单词的元组;和
  2. 然后我们在词典词典中转换Counter
  3. 这导致以下代码:

    from collections import Counter, defaultdict
    
    def word_counts(f):
        st = f.read().lower().split()
        ctr = Counter(zip(st,st[1:]))
        dc = defaultdict(dict)
        for (k1,k2),v in ctr.items():
            dc[k1][k2] = v
        return dict(dc)
    

答案 1 :(得分:5)

我们可以在一次通过

中执行此操作
  1. 使用defaultdict作为计数器。
  2. 迭代bigrams,就地计算
  3. 所以...为了简洁起见,我们将保持标准化和清理:

    >>> from collections import defaultdict
    >>> counter = defaultdict(lambda: defaultdict(int))
    >>> s = 'the dog chased the cat'
    >>> tokens = s.split()
    >>> from itertools import islice
    >>> for a, b in zip(tokens, islice(tokens, 1, None)):
    ...     counter[a][b] += 1
    ...
    >>> counter
    defaultdict(<function <lambda> at 0x102078950>, {'the': defaultdict(<class 'int'>, {'cat': 1, 'dog': 1}), 'dog': defaultdict(<class 'int'>, {'chased': 1}), 'chased': defaultdict(<class 'int'>, {'the': 1})})
    

    更可读的输出:

    >>> {k:dict(v) for k,v in counter.items()}
    {'the': {'cat': 1, 'dog': 1}, 'dog': {'chased': 1}, 'chased': {'the': 1}}
    >>>
    

答案 2 :(得分:1)

首先,那是一只追逐狗的勇敢的猫!其次,它有点棘手,因为我们不会每天与这种类型的解析交互。这是代码:

k = "The cat chased the dog."
sp = k.split()
res = {}
prev = ''
for w in sp:
    word = w.lower().replace('.', '')
    if prev in res:
        if word.lower() in res[prev]:
            res[prev][word] += 1
        else:
            res[prev][word] = 1
    elif not prev == '':
        res[prev] = {word: 1}
    prev = word
print res

答案 3 :(得分:1)

你可以:

  1. 创建已剥离的字词列表;
  2. 使用zip(list_, list_[1:])或任何按对方迭代的方法创建单词对;
  3. 创建对中第一个单词的词典,然后是该对中第二个单词的列表;
  4. 计算列表中的单词。
  5. 像这样:

    from collections import Counter
    s="The cat chased the dog."
    li=[w.lower().strip('.,') for w in s.split()] # list of the words
    di={}                                         
    for a,b in zip(li,li[1:]):                    # words by pairs
        di.setdefault(a,[]).append(b)             # list of the words following first
    
    di={k:dict(Counter(v)) for k,v in di.items()} # count the words
    >>> di
    {'the': {'dog': 1, 'cat': 1}, 'chased': {'the': 1}, 'cat': {'chased': 1}}
    

    如果你有一个文件,只需从文件中读取一个字符串然后继续。

    或者,你可以

    1. 前两个步骤
    2. 使用defaultdict作为Counter作为工厂。
    3. 像这样:

      from collections import Counter, defaultdict
      li=[w.lower().strip('.,') for w in s.split()]
      dd=defaultdict(Counter)
      for a,b in zip(li, li[1:]):
          dd[a][b]+=1
      
      >>> dict(dd)
      {'the': Counter({'dog': 1, 'cat': 1}), 'chased': Counter({'the': 1}), 'cat': Counter({'chased': 1})}
      

      或者,

      >>> {k:dict(v) for k,v in dd.items()}   
      {'the': {'dog': 1, 'cat': 1}, 'chased': {'the': 1}, 'cat': {'chased': 1}}
      

答案 4 :(得分:0)

我认为这是一个没有导入defaultdict的单程解决方案。它还有标点符号剥离。我试图为大文件或重复打开文件优化它

from itertools import islice

class defaultdictint(dict):
    def __missing__(self,k):
        r = self[k] = 0
        return r

class defaultdictdict(dict):
    def __missing__(self,k):
        r = self[k] = defaultdictint()
        return r

keep = set('1234567890abcdefghijklmnopqrstuvwxy ABCDEFGHIJKLMNOPQRSTUVWXYZ')

def count_words(file):
    d = defaultdictdict()
    with open(file,"r") as f:
        for line in f:
            line = ''.join(filter(keep.__contains__,line)).strip().lower().split()
            for one,two in zip(line,islice(line,1,None)):
                d[one][two] += 1
    return d

print (count_words("example.txt"))

将输出:

{'chased': {'the': 1}, 'cat': {'chased': 1}, 'the': {'dog': 1, 'cat': 1}}