Ваше редактирование, казалось, ухудшило ситуацию, в результате вы удалили много релевантного контекста.Я думаю, что собрал воедино то, что вы пытаетесь сделать.ядро этого, кажется, подпрограмма, которая выполняет анализ настроений над текстом.
Я бы начал с создания класса, который отслеживает это, например:
class Sentiment:
__slots__ = ('positive', 'neutral', 'negative')
def __init__(self, positive=0, neutral=0, negative=0):
self.positive = positive
self.neutral = neutral
self.negative = negative
def __repr__(self):
return f'<Sentiment {self.positive} {self.neutral} {self.negative}>'
def __add__(self, other):
return Sentiment(
self.positive + other.positive,
self.neutral + other.neutral,
self.negative + other.negative,
)
, который будетПозволяет вам заменить ваши извилистые биты кода, такие как [a + b for a, b in zip(map(int, dico_lexique[word]), d_score[k])]
на score += sentiment
в функции ниже, и позволяет нам ссылаться на различные значения по имени
. Затем я бы предложил предварительно обработать ваши засоленные данные, поэтомувам не нужно конвертировать вещи в int
s в середине несвязанного кода, например:
with open("dict_pickle", "rb") as fd:
dico_lexique = {}
for word, (pos, neu, neg) in pickle.load(fd):
dico_lexique[word] = Sentiment(int(pos), int(neu), int(neg))
, это помещает их непосредственно в вышеприведенный класс и, похоже, соответствует другим ограничениям в вашем коде,но у меня нет ваших данных, поэтому я не могу проверить.
после того, как вы разберете все ваши понимания и циклы, у нас останется одна приятная процедура для обработки одного фрагмента текста:
def process_text(text):
"""process the specified text
returns (words, filtered words, total sentiment score)
"""
words = []
filtered = []
score = Sentiment()
for tag in make_tags(tagger.tag_text(text)):
word = tag.lemma
words.append(word)
if word not in stopWords and lemma.isalpha():
filtered.append(word)
sentiment = dico_lexique.get(word)
if sentiment is not None:
score += sentiment
return words, filtered, score
и мы можем поместить это в цикл, который читает строки из входных данных и отправляет их в выходной файл:
filename = sys.argv[1]
tempname = filename + '~'
with open(filename) as fdin, open(tempname, 'w') as fdout:
inp = csv.reader(fdin, delimiter=';')
out = csv.writer(fdout, delimiter=';')
# get the header, and blindly append out column names
header = next(inp)
out.writerow(header + [
'd_lemma', 'd_filtered_words', 'Positive Score', 'Neutral Score', 'Negative Score',
])
for row in inp:
# assume that second item contains the text we want to process
words, filtered, score = process_text(row[1])
extra_values = [
words, filtered,
score.positive, score.neutal, score.negative,
]
# add the values and write out
assert len(row) == len(header), "code needed to pad the columns out"
out.writerow(row + extra_values)
# only replace if everything succeeds
os.rename(tempname, filename)
мы записываем в другой файл и переименовываем только в случае успеха, этоозначает, что в случае сбоя кода он не оставит частично записанные файлы.Хотя я бы не хотел работать так, как обычно, и заставлял бы мои сценарии читать из stdin
и писать в stdout
.таким образом, я могу работать как:
$ python script.py < input.csv > output.csv
, когда все в порядке, но также позволяет мне запускать как:
$ head input.csv | python script.py
, если я просто хочу проверить с первыми несколькими строками ввода, или:
$ python script.py < input.csv | less
если я хочу проверить вывод по мере его генерирования
обратите внимание, что ни один из этого кода не был запущен, так что, вероятно, в нем есть ошибки, но я действительно могу видетьчто код пытается сделать, как это.Понимание и «функциональный» стиль кода хороши, но они могут легко стать нечитаемыми, если вы не будете осторожны