【问题标题】:Adding new colums in a csv file and values from differents dictionaries-comprehension在 csv 文件中添加新列和来自不同字典的值 - 理解
【发布时间】:2019-05-01 12:28:36
【问题描述】:

这是我下面的代码,我想在我的原始 csv 中编写新列,这些列应该包含在我的代码期间创建的每个字典的值,我想要最后一个字典,因为它包含 3 个值,每个值都插入到单个列中。在 csv 中编写的代码在最后,但也许有一种方法可以在我每次生成新字典时写入值。

我的 csv 路由代码:我无法弄清楚如何在不删除原始文件内容的情况下添加


# -*- coding: UTF-8 -*-
# -*- coding: UTF-8 -*-
import codecs 
import re
import os
import sys, argparse
import subprocess
import pprint
import csv
from itertools import islice
import pickle
import nltk
from nltk import tokenize
from nltk.tokenize import sent_tokenize, word_tokenize
from nltk.corpus import stopwords
import pandas as pd

try:
    import treetaggerwrapper
    from treetaggerwrapper import TreeTagger, make_tags
    print("import TreeTagger OK")
except:
    print("Import TreeTagger pas Ok")

from itertools import islice
from collections import defaultdict

#export le lexique de sentiments
pickle_in = open("dict_pickle", "rb")
dico_lexique = pickle.load(pickle_in)


# extraction colonne verbatim
d_verbatim = {}

with open(sys.argv[1], 'r', encoding='cp1252') as csv_file:
    csv_file.readline()
    for line in csv_file:
        token = line.split(';')
        try:
            d_verbatim[token[0]] = token[1]
        except:
            print(line)

#print(d_verbatim)

#Using treetagger   
tagger = treetaggerwrapper.TreeTagger(TAGLANG='fr')
d_tag = {}
for key, val in d_verbatim.items(): 
        newvalues = tagger.tag_text(val)
        d_tag[key] = newvalues
#print(d_tag)


#lemmatisation  
d_lemma = defaultdict(list)
for k, v in d_tag.items():
    for p in v:
        parts = p.split('\t')
        try:
            if parts[2] == '':
                d_lemma[k].append(parts[0])
            else:
                d_lemma[k].append(parts[2]) 
        except:
            print(parts)
#print(d_lemma) 


stopWords = set(stopwords.words('french'))          
d_filtered_words = {k: [w for w in l if w not in stopWords and w.isalpha()] for k, l in d_lemma.items()}

print(d_filtered_words)     

d_score = {k: [0, 0, 0] for k in d_filtered_words.keys()}
for k, v in d_filtered_words.items():
    for word in v:
        if word in dico_lexique:
            if word 
            print(word, dico_lexique[word]) 

【问题讨论】:

  • 我正在努力遵循您的代码,并怀疑其中大部分与问题无关。如果您可以删除与问题无关的详细信息,它可能会得到一些答案,例如您的大量 imports 似乎不需要或被重复,并且您对列表/字典理解的大量使用让我感到困惑

标签: python csv list-comprehension writer dictionary-comprehension


【解决方案1】:

您的编辑似乎让事情变得更糟,您最终删除了很多相关的上下文。我想我已经拼凑了你想要做的事情。它的核心似乎是一个对文本进行情感分析的例程。

我会首先创建一个跟踪这个的类,例如:

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,
        )

这将允许您在下面的函数中用score += sentiment 替换像[a + b for a, b in zip(map(int, dico_lexique[word]), d_score[k])] 这样复杂的代码,并允许我们按名称引用各种值

然后我建议预处理您的腌制数据,因此您不必在不相关的代码中间将内容转换为 ints,例如:

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

如果我想在生成时检查输出

请注意,这段代码都没有运行过,因此其中可能存在错误,但我实际上可以看到代码试图这样做。理解和“功能”风格的代码很棒,但如果你不小心,它很容易变得难以阅读

【讨论】:

  • 当我运行代码时出现以下错误:for word, (pos, neu, neg) in pickle.load(fd): ValueError: too many values to unpack (expected 2)跨度>
  • 那么您需要确保您的数据符合代码的要求!即上面的代码假设dict_pickle文件是特定格式的,有很多这样的基础教程
猜你喜欢
  • 2019-08-22
  • 1970-01-01
  • 2019-09-01
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
  • 2020-05-25
  • 2022-01-04
  • 1970-01-01
相关资源
最近更新 更多