Сравнение значений одного хэша со многими хэшами, чтобы получить обратную частоту документов в рубине

Я пытаюсь найти частоту инверсного документа для алгоритма категоризации, и у меня возникают проблемы с его структурированием (с вложенными хэшами) и в целом сравниваю один хэш со многими хэшами.

Мой тренировочный код выглядит так:

def train!
    @data = {}
    @all_books.each do |category, books|
      @data[category] = {
        words: 0,
        books: 0,
        freq: Hash.new(0)
      }
      books.each do |filename, tokens|
        @data[category][:words] += tokens.count
        @data[category][:books] += 1

        tokens.each do |token|
          @data[category][:freq][token] += 1
        end

      end
      @data[category][:freq].map { |k, v| v = (v / @data[category][:freq].values.max) }
    end

  end

По сути, у меня есть хэш с 4 категориями (могут быть изменены), и для каждой из них есть количество слов, счетчик книг и хэш частоты, который показывает частоту терминов для категории. Как я могу получить частоту отдельных слов из одной категории по сравнению с частотой слов, показанных во всех категориях? Я знаю, как сделать сравнение для одного набора ключей хеша с другим, но я не уверен, как пройти через вложенный хэш, чтобы получить частоту терминов против всех других терминов, если это имеет смысл.

Изменить, чтобы включить прогнозируемый результат - я хотел бы вернуть хэш вложенных хэшей (по одному для каждой категории), который показывает слово в качестве ключа и число других категорий, в которых оно отображается в качестве значения. т.е. {:category1 = {:word => 3,:other => 2,:third => 1},:category2 => {:another => 1, ...}} Альтернативно массив имен категорий в качестве значения, а не количество категорий, также будет работать.

Я попытался создать новый хеш следующим образом, но он оказался пустым:

def train!
    @data = {}
    @all_words = Hash.new([]) #new hash for all words, default value is empty array

    @all_books.each do |category, books|
      @data[category] = {
        words: 0,
        books: 0,
        freq: Hash.new(0)
      }
      books.each do |filename, tokens|
        @data[category][:words] += tokens.count
        @data[category][:books] += 1

        tokens.each do |token|
          @data[category][:freq][token] += 1
          @all_words[token] << category #should insert category name if the word appears, right?
        end

      end
      @data[category][:freq].map { |k, v| v = (v / @data[category][:freq].values.max) }
    end

  end

Если кто-то может помочь мне выяснить, почему хеш @all_words пуст при выполнении кода, я могу получить остальное.

1 ответ

Решение

Я не прошел через все это, но у вас наверняка есть ошибка:

@all_words[token] << category #should insert category name if the word appears, right?

Нету. @all_words[token] вернет пустой массив, но не создаст новый слот с пустым массивом, как вы предполагаете. Так что это утверждение не изменяет @all_words хеш вообще.

Попробуйте эти 2 изменения и посмотрите, поможет ли это:

@all_words = {}                         # ditch the default value
...
(@all_words[token] ||= []) << category  # lazy-init the array, and append
Другие вопросы по тегам