#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 Устаревшая форма
!=
. Все еще работает в Py23. ‘<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]
.