Как отсортировать словарь по относительной частоте слов в двух txt файлах - PullRequest
1 голос
/ 30 мая 2020

Я пытаюсь написать код для чтения двух отдельных текстовых файлов, фильтрации общих слов, вычисления частоты слов в каждом файле и, наконец, вывода в порядке относительной частоты между двумя списками. Поэтому в идеале слова, которые относительно чаще встречаются в файле 1, должны отображаться вверху списка, слова, относительно более часто встречающиеся в файле 2, должны располагаться внизу списка, а те слова, которые встречаются в обоих файлах, должны находиться в середине. Например:

word, freq file 1, freq file 2    
Cat 5,0    
Dog 4,0    
Mouse 2,2    
Carrot 1,4    
Lettuce 0,5    
​

Мой код в настоящее время выводит слова в порядке их частоты в файле 1, но я не могу понять, как организовать список, чтобы слова, более распространенные в файле 2, появлялись в внизу списка. Я понимаю, что мне нужно вычесть частоту слов в файле 1 из частоты тех же слов в файле 2, но я не могу понять, как работать с кортежем в словаре ...

Пожалуйста, помогите!

import re

f1=open('file1.txt','r', encoding="utf-8") #file 1
f2=open('file2.txt','r', encoding="utf-8") #file 2

file_list = [f1, f2] # This will hold all the files

num_files = len(file_list)

stopwords = ["a", "and", "the", "i", "of", "this", "it", "but", "is", "in", "im", "my", "to", "for", "as", "on", "helpful", "comment", "report", "stars", "reviewed", "united", "kingdom", "was", "with", "-", "it", "not", "about", "which", "so", "at", "out", "abuse", "than","any", "if", "be", "can", "its", "customer", "dont", "just", "other", "too", "only", "people", "found", "helpful", "have", "wasnt", "purchase", "do", "only", "bought", "etc", "verified", "", "wasnt", "thanks", "thanx", "could", "think", "your", "thing", "much", "ive", "you", "they", "vine", "had", "more", "that"]

frequencies = {} # One dictionary to hold the frequencies

for i, f in enumerate(file_list):   # Loop over the files, keeping an index i
    for line in f:                                      # Get the lines of that file
        for word in line.split():           # Get the words of that file
            word = re.sub(r'[^\w\s]','',word) # Strip punctuation
            word = word.lower()                     # Make lowercase
            if not word in stopwords:           # Remove stopwords
                    if not word.isdigit():      # Ignore digits
                        if not word in frequencies:
                            frequencies[word] = [0 for _ in range(num_files)] # make a list of 0's for any word not seen yet -- one 0 for each file

                        frequencies[word][i] += 1   # Increment the frequency count for that word and file

frequency_sorted = sorted(frequencies, key=frequencies.get, reverse=True)
for r in frequency_sorted:
    print (r, frequencies[r])

Ответы [ 2 ]

1 голос
/ 30 мая 2020

Вы слишком усложняете. Это должно вам помочь:

import strings
from collections import Counter

def get_freqs( name ) :
    with open(name) as fin :
        text = fin.read().lower()

    words = ''.join( i if i in strings.ascii_letters else ' ' for i in text )
    words = [w for w in words.split() if len(w) > 0]
    return Counter( words )

freqs1 = get_freqs( 'file1.txt' )
freqs2 = get_freqs( 'file2.txt' )

all_words = set(freqs1.keys()) | set(freqs2.keys())  # - set(stop_words) ?
freqs_sorted = sorted( (freqs1[w], freqs2[w], w) for w in all_words )

Если вы беспокоитесь о стоп-словах, вы можете заменить all_words = set(freqs1.keys()) | set(freqs2.keys()) на all_words = set(freqs1.keys()) | set(freqs2.keys()) - set(stop_words) или что-то подобное.

0 голосов
/ 30 мая 2020

Может быть лучше, если аргумент key для sorted указывает на функцию, которая возвращает просто целое число, которое представляет собой разницу частот в двух файлах. Вот полное решение, включающее это.

import re

class FrequencyComparer:

    stopwords = {"a", "and", "the", "i", "of", "this", "it", "but", "is", "in", "im", "my", "to", "for", "as", "on", "helpful", "comment", "report", "stars", "reviewed", "united", "kingdom", "was", "with", "-", "it", "not", "about", "which", "so", "at", "out", "abuse", "than","any", "if", "be", "can", "its", "customer", "dont", "just", "other", "too", "only", "people", "found", "helpful", "have", "wasnt", "purchase", "do", "only", "bought", "etc", "verified", "", "wasnt", "thanks", "thanx", "could", "think", "your", "thing", "much", "ive", "you", "they", "vine", "had", "more", "that"}

    def __init__(self, file1, file2):
        self.freq1 = self.get_freqs_from_file(file1)
        self.freq2 = self.get_freqs_from_file(file2)

    def get_freqs_from_file(self, filename):
        matcher = re.compile("[^\w]*([\w']*)[^\w]*$").match
        freqs = {}
        with open(filename) as f:
            for line in f:
                for word in line.split():
                    m = matcher(word.lower())
                    if m:
                        w = m.group(1)
                        if w not in self.stopwords:
                            freqs[w] = freqs.get(w, 0) + 1
        return freqs

    def get_freqs_for_word(self, word):
        return (self.freq1.get(word, 0), self.freq2.get(word, 0))

    def get_relative_freq(self, word):
        freqs = self.get_freqs_for_word(word)
        return freqs[1] - freqs[0]

    def get_all_words(self):
        return set(set(self.freq1.keys()) | set(self.freq2.keys()))

    def get_all_words_by_relative_freq(self):
        all_words = self.get_all_words()
        return sorted(all_words, key=self.get_relative_freq)


fc = FrequencyComparer("file1.txt", "file2.txt")

for word in fc.get_all_words_by_relative_freq():
    print(word, fc.get_freqs_for_word(word))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...