Counting word frequency and making a dictionary from it

前端 未结 10 951
南旧
南旧 2020-12-05 21:08

I want to take every word from a text file, and count the word frequency in a dictionary.

Example: \'this is the textfile, and it is used to take words and co

相关标签:
10条回答
  • 2020-12-05 21:41

    If you don't want to use collections.Counter, you can write your own function:

    import sys
    
    filename = sys.argv[1]
    fp = open(filename)
    data = fp.read()
    words = data.split()
    fp.close()
    
    unwanted_chars = ".,-_ (and so on)"
    wordfreq = {}
    for raw_word in words:
        word = raw_word.strip(unwanted_chars)
        if word not in wordfreq:
            wordfreq[word] = 0 
        wordfreq[word] += 1
    

    for finer things, look at regular expressions.

    0 讨论(0)
  • 2020-12-05 21:44

    My approach is to do few things from ground:

    1. Remove punctuations from the text input.
    2. Make list of words.
    3. Remove empty strings.
    4. Iterate through list.
    5. Make each new word a key into Dictionary with value 1.
    6. If a word is already exist as key then increment it's value by one.

    text = '''this is the textfile, and it is used to take words and count'''
    word = '' #This will hold each word
    
    wordList = [] #This will be collection of words
    for ch in text: #traversing through the text character by character
    #if character is between a-z or A-Z or 0-9 then it's valid character and add to word string..
        if (ch >= 'a' and ch <= 'z') or (ch >= 'A' and ch <= 'Z') or (ch >= '0' and ch <= '9'): 
            word += ch
        elif ch == ' ': #if character is equal to single space means it's a separator
            wordList.append(word) # append the word in list
            word = '' #empty the word to collect the next word
    wordList.append(word)  #the last word to append in list as loop ended before adding it to list
    print(wordList)
    
    wordCountDict = {} #empty dictionary which will hold the word count
    for word in wordList: #traverse through the word list
        if wordCountDict.get(word.lower(), 0) == 0: #if word doesn't exist then make an entry into dic with value 1
            wordCountDict[word.lower()] = 1
        else: #if word exist then increament the value by one
            wordCountDict[word.lower()] = wordCountDict[word.lower()] + 1
    print(wordCountDict)
    

    Another approach:

    text = '''this is the textfile, and it is used to take words and count'''
    for ch in '.\'!")(,;:?-\n':
        text = text.replace(ch, ' ')
    wordsArray = text.split(' ')
    wordDict = {}
    for word in wordsArray:
        if len(word) == 0:
            continue
        else:
            wordDict[word.lower()] = wordDict.get(word.lower(), 0) + 1
    print(wordDict)
    
    0 讨论(0)
  • 2020-12-05 21:45

    Although using Counter from the collections library as suggested by @Michael is a better approach, I am adding this answer just to improve your code. (I believe this will be a good answer for a new Python learner.)

    From the comment in your code it seems like you want to improve your code. And I think you are able to read the file content in words (while usually I avoid using read() function and use for line in file_descriptor: kind of code).

    As words is a string, in for loop, for i in words: the loop-variable i is not a word but a char. You are iterating over chars in the string instead of iterating over words in the string words. To understand this, notice following code snippet:

    >>> for i in "Hi, h r u?":
    ...  print i
    ... 
    H
    i
    ,
     
    h
     
    r
     
    u
    ?
    >>> 
    

    Because iterating over the given string char by chars instead of word by words is not what you wanted to achieve, to iterate words by words you should use the split method/function from string class in Python.
    str.split(str="", num=string.count(str)) method returns a list of all the words in the string, using str as the separator (splits on all whitespace if left unspecified), optionally limiting the number of splits to num.

    Notice the code examples below:

    Split:

    >>> "Hi, how are you?".split()
    ['Hi,', 'how', 'are', 'you?']
    

    loop with split:

    >>> for i in "Hi, how are you?".split():
    ...  print i
    ... 
    Hi,
    how
    are
    you?
    

    And it looks like something you need. Except for word Hi, because split(), by default, splits by whitespaces so Hi, is kept as a single string (and obviously) you don't want that.

    To count the frequency of words in the file, one good solution is to use regex. But first, to keep the answer simple I will be using replace() method. The method str.replace(old, new[, max]) returns a copy of the string in which the occurrences of old have been replaced with new, optionally restricting the number of replacements to max.

    Now check code example below to see what I suggested:

    >>> "Hi, how are you?".split()
    ['Hi,', 'how', 'are', 'you?'] # it has , with Hi
    >>> "Hi, how are you?".replace(',', ' ').split()
    ['Hi', 'how', 'are', 'you?'] # , replaced by space then split
    

    loop:

    >>> for word in "Hi, how are you?".replace(',', ' ').split():
    ...  print word
    ... 
    Hi
    how
    are
    you?
    

    Now, how to count frequency:

    One way is use Counter as @Michael suggested, but to use your approach in which you want to start from empty an dict. Do something like this code sample below:

    words = f.read()
    wordfreq = {}
    for word in .replace(', ',' ').split():
        wordfreq[word] = wordfreq.setdefault(word, 0) + 1
        #                ^^ add 1 to 0 or old value from dict 
    

    What am I doing? Because initially wordfreq is empty you can't assign it to wordfreq[word] for the first time (it will raise key exception error). So I used setdefault dict method.

    dict.setdefault(key, default=None) is similar to get(), but will set dict[key]=default if key is not already in dict. So for the first time when a new word comes, I set it with 0 in dict using setdefault then add 1 and assign to the same dict.

    I have written an equivalent code using with open instead of single open.

    with open('~/Desktop/file') as f:
        words = f.read()
        wordfreq = {}
        for word in words.replace(',', ' ').split():
            wordfreq[word] = wordfreq.setdefault(word, 0) + 1
    print wordfreq
    

    That runs like this:

    $ cat file  # file is 
    this is the textfile, and it is used to take words and count
    $ python work.py  # indented manually 
    {'and': 2, 'count': 1, 'used': 1, 'this': 1, 'is': 2, 
     'it': 1, 'to': 1, 'take': 1, 'words': 1, 
     'the': 1, 'textfile': 1}
    

    Using re.split(pattern, string, maxsplit=0, flags=0)

    Just change the for loop: for i in re.split(r"[,\s]+", words):, that should produce the correct output.

    Edit: better to find all alphanumeric character because you may have more than one punctuation symbols.

    >>> re.findall(r'[\w]+', words) # manually indent output  
    ['this', 'is', 'the', 'textfile', 'and', 
      'it', 'is', 'used', 'to', 'take', 'words', 'and', 'count']
    

    use for loop as: for word in re.findall(r'[\w]+', words):

    How would I write code without using read():

    File is:

    $ cat file
    This is the text file, and it is used to take words and count. And multiple
    Lines can be present in this file.
    It is also possible that Same words repeated in with capital letters.
    

    Code is:

    $ cat work.py
    import re
    wordfreq = {}
    with open('file') as f:
        for line in f:
            for word in re.findall(r'[\w]+', line.lower()):
                wordfreq[word] = wordfreq.setdefault(word, 0) + 1
      
    print wordfreq
    

    Used lower() to convert an upper letter to lower letter.

    output:

    $python work.py  # manually strip output  
    {'and': 3, 'letters': 1, 'text': 1, 'is': 3, 
     'it': 2, 'file': 2, 'in': 2, 'also': 1, 'same': 1, 
     'to': 1, 'take': 1, 'capital': 1, 'be': 1, 'used': 1, 
     'multiple': 1, 'that': 1, 'possible': 1, 'repeated': 1, 
     'words': 2, 'with': 1, 'present': 1, 'count': 1, 'this': 2, 
     'lines': 1, 'can': 1, 'the': 1}
    
    0 讨论(0)
  • 2020-12-05 21:47
    wordList = 'this is the textfile, and it is used to take words and count'.split()
    wordFreq = {}
    
    # Logic: word not in the dict, give it a value of 1. if key already present, +1.
    for word in wordList:
        if word not in wordFreq:
            wordFreq[word] = 1
        else:
            wordFreq[word] += 1
    
    print(wordFreq)
    
    0 讨论(0)
提交回复
热议问题