Python:DictReader返回一个字典列表?

时间:2013-03-22 14:20:18

标签: python csv

我正在使用csv.DictReader()读取文件。它实际上返回一个字典列表,而不是一个字典。如何强制它返回单个字典,或者如何合并它返回的字典列表?

def agilent_e8361c_pna_read(file_loc):
    '''
    Load the '.s2p' file in to a dictionary.
    '''

    with open(file_loc) as f:
        # define the fields in the Agilent '.s2p' file
        col_names = ["f","s11","arg_s11","s21","arg_s21","s12","arg_s12","s22","arg_s22"]

        # read the data into a dictionary
        s2p_dicts = csv.DictReader(itertools.ifilter(n_input.is_comment, f), fieldnames=col_names, delimiter=' ')

    return s2p_dict

理想情况下,数据最初会被读入单个字典,永远不需要合并。这是一组数据。这些列属于一起,并且在没有完整集或相干子集的情况下是无意义的。如果DictReader没有“蟒蛇”能够胜任这一专长,我将决定合并词典列表。这应该不是科学家和程序员都喜欢用数据集做的不寻常的事情。

3 个答案:

答案 0 :(得分:4)

如果你想要key:listOfValues的词典,你可以这样做:

def transposeDict(listOfDicts):
    """Turn a list of dicts into a dict of lists.  Assumes all dicts in the list have the exact same keys."""

    keys = listOfDicts[0].iterkeys()
    return dict((key, [d[key] for d in listOfDicts]) for key in keys)

或者,在python2.7或更高版本中:

def transposeDict(listOfDicts):
    """Turn a list of dicts into a dict of lists.  Assumes all dicts in the list have the exact same keys."""

    keys = listOfDicts[0].iterkeys()
    return {key: [d[key] for d in listOfDicts] for key in keys}

当然,这假设列表中的所有dicts都具有完全相同的密钥 - 它们将来自DictReader。

一般情况下,如果情况并非如此,则需要执行类似

的操作
from collections import defaultdict

def transposeListOfDicts(listOfDicts):
    """Turn a list of dict into a dict of lists"""

    result = defaultdict(list)

    for d in listofDicts:
        for key, value in d.iteritems():
            result[key].append(item)

    return result

如果您希望占位符显示缺失值,则它看起来像这样:

def transposeListOfDicts(listOfDicts):
    keys = {}
    for d in listOfDicts:
        keys.update(d.iterkeys())

    return {key: [d.get(key, None) for d in listOfDicts] for key in keys}

答案 1 :(得分:3)

DictReader会使每一行定期csv.reader()返回,并根据您传入或从第一行读取的字段名将其转换为字典。这是设计的。

如果您的输入文件只包含一个行,请通过在阅读器上调用next()来返回该行:

def agilent_e8361c_pna_read(file_loc):
    with open(file_loc) as f:
        col_names = ["f","s11","arg_s11","s21","arg_s21","s12","arg_s12","s22","arg_s22"]

        reader = csv.DictReader(itertools.ifilter(n_input.is_comment, f), fieldnames=col_names, delimiter=' ')
        return next(reader)

请注意next()调用应位于while块内,否则文件将在您阅读之前关闭。

如果需要将行合并到一个字典中,则需要说明如何查看合并的数据。您可以轻松地将行合并到每个键的列表中:

import csv

def agilent_e8361c_pna_read(file_loc):
    with open(file_loc) as f:
        col_names = ["f","s11","arg_s11","s21","arg_s21","s12","arg_s12","s22","arg_s22"]
        result = {k: [] for k in col_names}

        reader = csv.reader(itertools.ifilter(n_input.is_comment, f), fieldnames=col_names, delimiter=' ')
        for row in reader:
            for k, v in zip(col_names, row):
                result[k].append(v)

        return result

此时我们不再需要DictReader了,因为我们这里没有为每行构建字典。

答案 2 :(得分:1)

好的,这是最优雅的解决方案,任何人都有这个问题。

def agilent_e8361c_pna_read(file_loc):
    '''
    Load the '.s2p file in to a dictionary.
    '''

    with open(file_loc) as f:
        # read the data into a dictionary
        rows = csv.reader(itertools.ifilter(n_input.is_comment, f), delimiter=' ')

        # transpose data
        cols = transpose(rows)

        # create a dictionary with intuitive key names
        col_names = ["f","s11","arg_s11","s21","arg_s21","s12","arg_s12","s22","arg_s22"]
        s2p_dict = dict(zip(col_names,cols))

    return s2p_dict

def transpose(l):
    return map(list, zip(*l))
相关问题