Не удается получить доступ к вложенному словарю в python

#python #loops #dictionary

#python #циклы #словарь

Вопрос:

Введение:

Я пытаюсь получить доступ к элементу вложенного словаря в python, который выглядит следующим образом:

{'CA':{'1':'3','2':'3','3':'3'},'IL': {'1':'31','2':'45','3':'23'},...}

Сначала я читаю из файла Excel, где я получаю названия состояний, а затем присваиваю словарь каждому состоянию. Вот как я это делаю:

 xls_file = pd.ExcelFile('D:/CollegeScorecardDataDictionary-08-18-2016.xlsx')
dfEx = xls_file.parse('Church')  # Parse Church sheet
for (i, item) in enumerate(stateName):
     if stateChurchDict.get(item)<>None:
            continue 
     else:
            stateChurchDict[item] = dict
  

Как только цикл повторяется, у меня получается что-то вроде этого:

{'CA':<type dict>,'IL': <type dict>,'AL': <type dict>...}

В каждом штате есть множество церквей, которые могут быть классифицированы в любом из '1', '2' or '3' Здесь я получил номера во вложенных словарях.

Моя проблема в том, что я хочу обратиться к вложенному словарю определенного состояния, например

stateChurchDict['AL']['3']

и получить количество церквей в категории ‘3’ в определенном состоянии. Однако, сначала я должен проверить, пусто оно или нет, если оно пустое, то значение должно быть добавлено. Таким образом, я придумал это:

 for (i, item) in enumerate(stateName):
            if stateChurchDict[stateName[i-1]]['3'] <> None:
                stateChurchDict.update({stateChurchDict[stateName[i-1]]['3']: stateChurchDict[stateName[i-1]]['3']   1})
            else:
                stateChurchDict[stateName[i-1]]['3'] = 1
  

НО, однако, это stateChurchDict[stateName[i-1]]['3'] не может получить доступ к вложенному словарю stateName[i-1] == 'AL' и вызывает элемент like stateChurchDict['AL']['3'] и по-прежнему ничего.

Любая помощь приветствуется.

Я публикую весь материал для лучшего объяснения:

 import pandas as pd
from collections import defaultdict, Counter
def IsNumeric(x):
    try:
        float(x)
        return x
    except:
        return 0
xls_file = pd.ExcelFile('D:/CollegeScorecardDataDictionary-08-18-2016.xlsx')
dfEx = xls_file.parse('Church')  # Parse data_dictionary sheet
dfCsv = pd.read_csv('D:/MERGED2014_15_PP.csv', low_memory=False)
churchCode = dfEx.Code  # Label column
churchName = dfEx.ChurchName  # Value column
churchCategory = dfEx.Category  # Church category
relafil = dfCsv.RELAFFIL  # Religious Id in CSV
stateName = dfCsv.STABBR  # Name of state
churchList = {}  # Create dictionary to store churches
stateChurchDict = defaultdict(Counter)  # Create dictionary to store churches by state
stateChurchTemp = {} #Sepate dictionary for churches by state
# Put values into dictionary
for (i, v) in enumerate(churchCode):
    churchList[v] = churchCategory[i] #Assigns a category to each church in state

for (i, item) in enumerate(stateName): #Create a dictionary as a value to each state in the stateChurchList dictionary
    if item <> None:
        if stateChurchDict.get(item) <> None:
            continue
        else:
            stateChurchDict[item] = {}

for (i, item) in enumerate(stateName): #Iterate through states and count the number of churches by categories. Once the state name is changed, the number needs to be transferred from stateChurchTemp to stateChurchDict
    if IsNumeric(relafil[i]) <> 0:
        if i >= 1 and item <> stateName[i - 1]:
            if stateChurchDict[stateName[i - 1]][3] <> None:
                stateChurchDict.update({stateChurchDict[stateName[i - 1]][3]: stateChurchDict[stateName[i - 1]][
                                                                                    3]   IsNumeric(
                    stateChurchTemp[3])})
            else:
                stateChurchDict[stateName[i - 1]][3] = IsNumeric(stateChurchTemp[3])
            if stateChurchDict[stateName[i - 1]][2] <> None:
                stateChurchDict.update({stateChurchDict[stateName[i - 1]][2]: stateChurchDict[stateName[i - 1]][
                                                                                    2]   IsNumeric(
                    stateChurchTemp[2])})
            else:
                stateChurchDict[stateName[i - 1]][2] = IsNumeric(stateChurchTemp[2])
            if stateChurchDict[stateName[i - 1]][1] <> None:
                stateChurchDict.update({stateChurchDict[stateName[i - 1]][1]: stateChurchDict[stateName[i - 1]][
                                                                                    1]   IsNumeric(
                    stateChurchTemp[1])})
            else:
                stateChurchDict[stateName[i - 1]][1] = IsNumeric(stateChurchTemp[1])
        if churchList.get(relafil[i]) <> None and stateChurchTemp.get(churchList.get(relafil[i])) <> None:
            stateChurchTemp.update({churchList.get(relafil[i]): stateChurchTemp.get(churchList.get(relafil[i]))   1})
        else:
            stateChurchTemp[churchList.get(relafil[i])] = 1
print stateChurchDict
  

Комментарии:

1. Где вы это видели <> ?

2. @PadraicCunningham Устаревшая форма != . Все еще работает в Py2

3. ‘<type dict>’ — это новый словарь, который еще не заполнен данными.

4. Используйте '3' in stateChurchDict[stateName[i-1] , чтобы проверить, присутствует ли ‘3’ в dict или нет.

5. @RustamUmarov, назначьте его как stateChurchDict[item] = {} , вы можете найти collections.defaultdict здесь своего друга. Также ваш enumerate является избыточным, и вы могли бы просто создать dict как {item:{} for item in stateName }

Ответ №1:

Вы вызываете не вложенный словарь, вы пытаетесь обновить основной. Пожалуйста, измените эту строку:

 stateChurchDict.update({stateChurchDict[stateName[i - 1]][2]: stateChurchDict[stateName[i - 1]][2]   IsNumeric(stateChurchTemp[2])})
  

с помощью этого:

 stateChurchDict.get(statename[i-1]).update({3: stateChurchDict[stateName[i - 1]][3]   IsNumeric(stateChurchTemp[3])})
  

Ответ №2:

stateChurchDict вероятно, изначально не следовало использовать ванильный словарь.

Здесь A collections.Counter передается в a collections.defauldict в правильном направлении:

 >>> from collections import defaultdict, Counter
>>> d = defaultdict(Counter) # or defaultdict(lambda: defaultdict(int))
>>> d['AL']['3']
0
  

При этом значения счетчика по умолчанию генерируются «на лету» для ключей, вложенных до двух уровней, и ваш код сводится к:

 from collections import defaultdict, Counter

stateChurchDict = defaultdict(Counter)
for i, item in enumerate(stateName):
    stateChurchDict[stateName[i-1]]['3']  = 1
  

Комментарии:

1. Бьюсь об заклад, вы что-то упускаете, поскольку это не должно вызывать KeyError . Как вы это реализовали?

2. Вы хотите увидеть весь материал?

3. У вас проблемы с вашим кодом, например, stateChurchDict[item] = {} заменит Counter объект обычным словарем. Этот начальный цикл for больше не понадобится. И словарь также обновляется. Вероятно, вам следует взглянуть на ссылки для defaultdict и Counter

Ответ №3:

Хорошо, вот как я пришел к ответу. Просто я создал другой словарь internalDict , в котором хранятся значения вложенного словаря.

Вместо вызова stateChurchDict[stateName[i-1][3]] я попробовал internalDict = stateChurchDict[stateName[i-1]] , а затем работал только с internalDict . В результате вызывался stateChurchDict[stateName[i-1][3]] подобный internalDict[3] .