Ошибка типа: индексы списка должны быть целыми или фрагментами, а не str в Windows 10

#python #artificial-intelligence #nltk #frequency #word-frequency

#python #искусственный интеллект #nltk #частота #частота слов

Вопрос:

Я пытаюсь выяснить обратную частоту документов списка историй о Шерлоке Холмсе. Взгляните на код:

Обратная частота документа — это показатель того, насколько распространено или редко встречается слово в нескольких документах.

Таким образом, это означало бы, что обратная частота документов или idf , для краткости, измеряет, насколько распространено слово в конкретном документе, которое не так часто встречается в других.

Формула для idf такова: log x (Total_Documents/The_Number_Of_Documents_Containing(word))

main.py

 import math
import nltk
import os
import sys


def main():

    if len(sys.argv) != 2:
        sys.exit("Usage: python main.py corpus")
    print("Loading data...")
    corpus = load_data(sys.argv[1])

    words = set()
    for filename in corpus:
        words.update(corpus[filename])

    idfs = list()
    for word in words:
        f = sum(word in corpus[filename] for filename in corpus)
        idf = math.log(len(corpus) / f)
        idfs[word] = idf

    tfidfs = dict()
    for filename in corpus:
        tfidfs[filename] = []
        for word in corpus[filename]:
            tf = corpus[filename][word]
            tfidfs[filename].append((word, tf * idfs[word]))

    for filename in corpus:
        tfidfs[filename].sort(key=lambda tfidf: tfidf[1], reverse=True)
        tfidfs[filename] = tfidfs[filename][:5]

    print()
    for filename in corpus:
        print(filename)
        for term, score in tfidfs[filename]:
            print(f"    {term}: {score:.4f}")


def load_data(directory):
    files = dict()
    for filename in os.listdir(directory):
        with open(os.path.join(directory, filename)) as f:

            contents = [
                word.lower() for word in
                nltk.word_tokenize(f.read())
                if word.isalpha()
            ]

            frequencies = dict()
            for word in contents:
                if word not in frequencies:
                    frequencies[word] = 1
                else:
                    frequencies[word]  = 1
            files[filename] = frequencies

    return files


if __name__ == "__main__":
    main()
  

Но когда я запускаю python .main.py .shelock_holmes в Powershell,

Я получаю эту запутанную ошибку:

 Loading data...
Traceback (most recent call last):
  File ".main.py", line 65, in <module>
    main()
  File ".main.py", line 22, in main
    idfs[word] = idf
TypeError: list indices must be integers or slices, not str
  

Кто-нибудь может мне помочь?

Комментарии:

1. На самом деле, сообщение об ошибке содержит достаточно информации, я не знаю, что можно добавить.

2. Ну, он показывает вам строку кода, в которой говорится idfs[word] = idf . Это означает, что у вас есть список idfs , который вы хотите использовать word в качестве индекса. В сообщении об ошибке говорится, что существует ошибка TypeError, то есть ошибка, связанная с типом чего-либо. Затем он сообщает вам, что то, что вы пытаетесь использовать в качестве индекса (т. Е. word ), является string ( str ) , и что вместо этого для индексации в список требуется целое число или фрагмент. Что именно в этом сбивает с толку? Тщательно подумайте о том, какую проблему вы хотите решить с помощью этой строки кода.

3. Привет! Вы знаете, мне 12 лет!

Ответ №1:

Вы определяете idfs как список:

 idfs = list()
  

Если udfs это список, то в этом назначении:

 idfs[word] = idf
  

word должно быть целым числом, поскольку оно указывает индекс или позицию в списке.

Но похоже, что words это список str , и так внутри итерации:

 for word in words:
  

word является str . Поскольку a str не является целым числом, строка

 idfs[word] = idf
  

вызывает ошибку, которую вы получаете, именно по той причине, которую она объясняет. Возможно idfs , это должен быть a dict , а не список, определенный следующим образом:

 idfs = dict()
  

Затем строка:

 idfs[word] = idf
  

интерпретируется word как ключ в словаре и присваивается idf как значение этого ключа в dict . Ключи словаря могут быть любым объектом и чаще всего являются строками, так что это имеет смысл.

Ответ №2:

На самом деле idfs это список. И idfs[word] = idf добавляет к нему ключевые значения, как словарь. Поэтому вы должны вместо idfs = list() этого сделать его idfs = {} словарем. В противном случае, если вам нужен список, используйте .append() для добавления элементов в конец.