2017-01-15 4 views
0

Как эффективно обрабатывать словарь Python с помощью динамических клавиш?Как эффективно обрабатывать словарь Python с помощью динамических клавиш?

Работаю с открытыми данными из Нидерландов. Существует словарь для каждой области/года. Клавиши словаря различаются для каждого года. Как я могу написать эффективный код, связанный с этим?

У меня есть две рабочие конструкции, как в примерах ниже: Но оба требуют усилий для каждого ключа, а в открытых данных есть 108 ключей, поэтому я действительно надеюсь, что Python предлагает лучшее решение, о котором я еще не знаю!

FYI об открытых данных: Каждый год представляет собой список из 16194 словарей. Один словарь для каждой окрестности в NL. Каждый словарь имеет 108 пунктов (пар ключ, значение):

>>> import cbsodata 
>>> table = '83487NED' 
>>> data = cbsodata.get_data(table, dir=None, typed=False) 
Retrieving data from table '83487NED' 
Done! 
>>> len(data) 
16194 
>>> data[0] 
{'Gehuwd_14': 1565, 'MateVanStedelijkheid_105': 5, 'Bevolkingsdichtheid_33': 1350, 'Gemeentenaam_1': 'Aa en Hunze        ', ... etc  
>>> len(data[0]) 
108 

Ключ может быть «Code_3» в течение одного года и «Code_4» в следующем году ...

Пример данных, используемых, например, растворы :

data2016 = [{'Code_3': 'BU01931000', 'ZipCode_106': '2251MT', 'City_12': 'Amsterdam', 'Number_of_people_5': '24000'}, 
       {'Code_3': 'BU02221000', 'ZipCode_106': '2851MT', 'City_12': 'London', 'Number_of_people_5': '88000'}, 
       {'Code_3': 'BU04444000', 'ZipCode_106': '2351MT', 'City_12': 'Paris', 'Number_of_people_5': '133000'}] 
data2015 = [{'Code_4': 'BU01931000', 'ZipCode_106': '2251MT', 'City_12': 'Amsterdam', 'Number_of_people_6': '22000'}, 
       {'Code_4': 'BU02221000', 'ZipCode_106': '2851MT', 'City_12': 'London', 'Number_of_people_6': '86000'}, 
       {'Code_4': 'BU04444000', 'ZipCode_106': '2351MT', 'City_12': 'Paris', 'Number_of_people_6': '131000'}] 
data2014 = [{'Code_8': 'BU01931000', 'ZipCode_109': '2251MT', 'City_12': 'Amsterdam', 'Number_of_people_14': '18000'}, 
       {'Code_8': 'BU02221000', 'ZipCode_109': '2851MT', 'City_12': 'London', 'Number_of_people_14': '76000'}, 
       {'Code_8': 'BU04444000', 'ZipCode_109': '2351MT', 'City_12': 'Paris', 'Number_of_people_14': '129000'}] 
data2013 = [{'Code_8': 'BU01931000', 'ZipCode_109': '2251MT', 'City_12': 'Amsterdam', 'Number_of_people_14': '14000'}, 
       {'Code_8': 'BU02221000', 'ZipCode_109': '2851MT', 'City_12': 'London', 'Number_of_people_14': '74000'}] # data for Paris 'BU04444000' missing in 2013 
tables = {2013: data2013, 2014: data2014, 2015: data2015, 2016: data2016} 
years = [2013, 2014, 2015, 2016] 
current_year = 2016 

Пример 1 раствор, отображение ключей:

def CBSkey(key, year): 
    if key == 'key_code': 
     if year == 2013: 
      return('Code_8') 
     elif year == 2014: 
      return('Code_8') 
     elif year == 2015: 
      return('Code_4') 
     elif year == 2016: 
      return('Code_3') 
    elif key == 'key_people': 
     if year == 2013: 
      return('Number_of_people_14') 
     elif year == 2014: 
      return('Number_of_people_14') 
     elif year == 2015: 
      return('Number_of_people_6') 
     elif year == 2016: 
      return('Number_of_people_5') 

for record_now in tables[current_year]: 
    code = record_now['Code_3'] 
    city = record_now['City_12'] 
    people = {} 
    for year in years: 
     code_year = CBSkey('key_code', year) 
     people_year = CBSkey('key_people', year) 
     for record in tables[year]: 
      if record[code_year] == code: 
       people[year] = (record[people_year]) 

    print(people) 

Выход для всех 3 Пример решения:

{2016: '24000', 2013: '14000', 2014: '18000', 2015: '22000'} 
{2016: '88000', 2013: '74000', 2014: '76000', 2015: '86000'} 
{2016: '133000', 2014: '129000', 2015: '131000'} 

Пример 2, выберите правильный словарь, основанный на элементе, а затем перебрать все другие ключи, чтобы найти дополнительные данные:

for record_now in tables[current_year]: 
    city = record_now['City_12'] 
    code = record_now['Code_3'] 
    print('Code: ', code) 
    people = {} 
    for year in years: 
     for record in tables[year]: 
      for v in record.values(): 
       if v == code: 
        for k in record.keys(): 
         key_type = CBSkey(k) 
         if key_type == 'People_type': 
          people[year] = (record[k]) 
    print(people) 

Надеясь для некоторых ярких идей «вещих», большое спасибо заранее!

+0

Это довольно длинный и подробный. Пожалуйста, ознакомьтесь с [минимальными рабочими примерами] (http://stackoverflow.com/help/mcve). –

+0

Спасибо Том. Я удалил около 40%! – Wouter

ответ

1

Если я правильно понял этот набор данных, данные за каждый год представляют собой список многих dict; все диктофоны за определенный год используют одни и те же ключи; ключи отличаются от года к году, но общие данные доступны одинаково. Итак, вам нужен способ эффективного извлечения одних и тех же данных из нескольких лет.

Во-первых, я бы поставил все эти годы в один большой Словаре, вместо того, чтобы использовать косвенная схема отображения у вас есть:

data = {} 
data[2016] = [{'Code_3': 'BU01931000'}] # etc. 
data[2015] = [{'Code_4': 'BU01931000'}] # etc. 

Так tables и все отдельные datayyyy уходят, tables[year] становится data[year] , и years будет data.keys().

Затем я разработал картографирование года с помощью клавиш.

"""ytok structure 

ytok maps years to dicts of keys. ytok[2016] would be: 
{'code': 'Code_3', 'zip': 'ZipCode_106', 'city': 'City_12', 
'people': 'Number_of_people_5'} 
""" 

Вот один из способов построить ytok, показывающий промежуточные результаты сделать процесс ясный:

ytok = {} 

for year in data.keys(): 
    sample = data[year][0] 
    outputs = list(sorted(sample.keys())) 
    # Will be in this order: city, code, people, zip 
    inputs = 'city code people zip'.split() 
    pairs = list(zip(inputs, outputs)) 
    print(pairs) 
    yeardict = dict(pairs) 
    print(yeardict) 
    ytok[year] = yeardict 

print(ytok) 

Вот более обтекаемый путь:

inputs = 'city code people zip'.split() 
for year in data.keys(): 
    outputs = sorted(data[year][0].keys()) 
    ytok[year] = dict(zip(inputs, outputs)) 

print(ytok) 

Затем с помощью ytok, как так:

wanted_code = 'BU02221000' 
people = {} 
for year in data.keys(): 
    codekey = ytok[year]['code'] 
    peoplekey = ytok[year]['people'] 
    for record in data[year]: 
     if record[codekey] == wanted_code: 
      people[year] = record[peoplekey] 
      break 

print(people) 

Обратите внимание на использование break после того, как правильная запись была найдена. Там нет смысла продолжать поиск года, как только мы найдем то, что хотим, , поэтому мы выходим из внутреннего цикла for record.

+0

Спасибо за это приятное решение! – Wouter

+0

Рад, что это было полезно :) –

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