2015-03-13 5 views
4

У меня есть файл CSV, который я фильтровал в список и сгруппировал. Пример:Python - вложенный словарь. Где ошибка?

 52713 
    ['52713', '', 'Vmax', '', 'Start Value', '', '\n'] 
    ['52713', '', 'Vmax', '', 'ECNumber', '1.14.12.17', '\n'] 
    ['52713', 'O2', 'Km', 'M', 'Start Value', '3.5E-5', '\n'] 
    ['52713', 'O2', 'Km', 'M', 'ECNumber', '1.14.12.17', '\n'] 
    52714 
    ['52714', '', 'Vmax', '', 'Start Value', '', '\n'] 
    ['52714', '', 'Vmax', '', 'ECNumber', '1.14.12.17', '\n'] 
    ['52714', 'O2', 'Km', 'M', 'Start Value', '1.3E-5', '\n'] 
    ['52714', 'O2', 'Km', 'M', 'ECNumber', '1.14.12.17', '\n'] 

Из этого я создать вложенный словарь со структурой:

dict = ID number:{Km:n, Kcat:n, ECNumber:n} 

... для каждого идентификатора в списке.

Я использую следующий код, чтобы создать этот словарь

dict = {} 

    for key, items in groupby(FilteredTable1[1:], itemgetter(0)): 
     #print key 
     for subitem in items: 
      #print subitem 
      dict[subitem[EntryID]] = {} 
      dict[subitem[EntryID]]['EC'] = [] 
      dict[subitem[EntryID]]['Km'] = [] 
      dict[subitem[EntryID]]['Kcat'] = [] 
      if 'ECNumber' in subitem: 
       dict[subitem[EntryID]]['EC'] = subitem[value] 

      if 'Km' in subitem and 'Start Value' in subitem: 
       dict[subitem[EntryID]]['Km'] = subitem[value] 
       #print subitem 

Это работает для значения ECNumber, но не значение Km. Он может распечатать строку, показывая, что она идентифицирует значение Km как присутствующее, но не помещает его в словарь.

Пример вывода:

{'Km': [], 'EC': '1.14.12.17', 'Kcat': []} 

Любые идеи?

Бен

+1

Почему downvote его, а затем оставить никаких объяснений? Является ли ответ простым? –

+1

Каково содержание 'value'? – Matthias

+0

@Matthias Просто указатель для списка. В этом случае целое число 6. Я попытался заменить значение на 6. Не повезло. –

ответ

2

Проблема заключается в том, что ваша внутренняя for петля удерживает переинициализация dict[subitem[EntryID]], даже если она уже существует. Вот фиксируется в следующем явным образе проверять, если она уже есть:

dict = {} 

for key, items in groupby(FilteredTable1[1:], itemgetter(0)): 
    #print key 
    for subitem in items: 
     #print ' ', subitem 
     if subitem[EntryID] not in dict: 
      dict[subitem[EntryID]] = {} 
      dict[subitem[EntryID]]['EC'] = [] 
      dict[subitem[EntryID]]['Km'] = [] 
      dict[subitem[EntryID]]['Kcat'] = [] 

     if 'ECNumber' in subitem: 
      dict[subitem[EntryID]]['EC'] = subitem[value] 

     if 'Km' in subitem and 'Start Value' in subitem: 
      dict[subitem[EntryID]]['Km'] = subitem[value] 
      #print subitem 

Однако этот код может быть более эффективным, используя что-то вроде следующего вместо этого, что позволяет избежать повторного вычисления значений и двойной словарный поиск. Он также не использует имя встроенного типа для имени переменной, что противоречит рекомендациям, приведенным в PEP8 - Style Guide for Python Code. Он также предлагает использовать CamelCase только для имен классов, а не для имен переменных, таких как FilteredTable1, но я не изменил это.

adict = {} 

for key, items in groupby(FilteredTable1[1:], itemgetter(0)): 
    #print key 
    for subitem in items: 
     #print ' ', subitem 
     entry_id = subitem[EntryID] 
     if entry_id not in adict: 
      adict[entry_id] = {'EC': [], 'Km': [], 'Kcat': []} 

     entry = adict[entry_id] 
     if 'ECNumber' in subitem: 
      entry['EC'] = subitem[value] 

     if 'Km' in subitem and 'Start Value' in subitem: 
      entry['Km'] = subitem[value] 
      #print subitem 

На самом деле, так как вы создаете словарь словарей, не ясно, что есть какие-либо преимущества в использовании groupby сделать это.

+0

Спасибо! Большое спасибо –

1

Я отправляю это для последующего наблюдения и продюсирования на своем previous answer.

Для начала, вы могли бы оптимизировать код немного дальше, устраняя необходимость проверки для уже существующих записей просто сделать словарь создается с collections.defaultdictdict подкласс вместо обычного одного:

from collections import defaultdict 
adict = defaultdict(lambda: {'EC': [], 'Km': [], 'Kcat': []}) 

for key, items in groupby(FilteredTable1[1:], itemgetter(0)): 
    for subitem in items: 
     entry = adict[subitem[EntryID]] 
     if 'ECNumber' in subitem: 
      entry['EC'] = subitem[value] 

     if 'Km' in subitem and 'Start Value' in subitem: 
      entry['Km'] = subitem[value] 

Во-вторых, в качестве Я упомянул в другом ответе, я не думаю, что вы набираете что-либо, используя itertools.groupby(), чтобы сделать это, за исключением того, что процесс стал более сложным, чем необходимо. Это потому, что в основном то, что вы делаете, - это словарь словарей, чьи записи могут быть случайным образом доступны, поэтому нет никакой выгоды в том, чтобы сгруппировать их до этого. Приведенный ниже код доказывает это (в сочетании с использованием defaultdict как показано выше):

adict = defaultdict(lambda: {'EC': [], 'Km': [], 'Kcat': []}) 

for subitem in FilteredTable1[1:]: 
    entry = adict[subitem[EntryID]] 
    if 'ECNumber' in subitem: 
     entry['EC'] = subitem[value] 

    if 'Km' in subitem and 'Start Value' in subitem: 
     entry['Km'] = subitem[value] 
+0

Спасибо за продолжение. Раньше я не сталкивался с дефолтом. Очень полезно знать. –

Смежные вопросы