-1

我正在使用 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 不能“以python 方式”实现这一壮举,我将决定只合并字典列表。这不应该是科学家和程序员都想用数据集做的一件不寻常的事情。

4

3 回答 3

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}
于 2013-03-22T14:32:30.230 回答
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

那时我们不再需要 a DictReader,因为我们没有在这里为每行构建一个字典。

于 2013-03-22T14:27:31.703 回答
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))
于 2013-03-22T15:22:11.427 回答