2013-03-22 186 views
-2

我正在使用csv.DictReader()来读取文件。它实际上返回一个字典列表,而不是单个字典。我如何强制它返回单个字典,或者如何合并它返回的字典列表?Python: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不是“pythonically”能够完成这个壮举,我将决定合并词典列表。这不应该是科学家和程序员都想要用数据集所做的不常见的事情。

+1

为什么会返回单个字典?它为输入文件中的每一行返回一个字典,这就是它的意图。 – 2013-03-22 14:21:43

+0

如果你输入的文件只包含* 1 *行,只需选择那一行:'return next(s2p_dict)'。 – 2013-03-22 14:23:32

+0

如果它包含多行,您是如何预期数据将被映射到字典的键? – 2013-03-22 14:24:27

回答

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} 

当然,这个假设中的所有类型的字典该列表具有完全相同的密钥 - 它们将来自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} 
+0

这是一个非常好的答案。感谢您花时间发布它! – 2013-03-22 14:57:11

+2

我也许在工作中有点无聊...... – RoadieRich 2013-03-22 14:57:23

2

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了在这一点上,因为我们没有建立每行一本字典在这里。

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)) 
+0

不能保证'dict'中的项目总是以相同的顺序返回(参见http://docs.python.org/2/library/stdtypes.html #dict.items),所以你可以看到列混合起来。 此外,注释“将列表转换为字典”是不准确的,因为“行”不是“list”的“列表”,并且“transpose()”的返回值是“list”不是'dict'。 – RoadieRich 2013-03-22 15:31:59

+0

@RoadieRich你是对的 - 该评论已经失效。所以你基本上不会想用字典来存储有序对呢? – 2013-03-22 15:41:45

+0

@RoadieRich其实,如果你所做的只是迭代,顺序不会改变。 – 2013-03-22 15:44:02