Reputation: 4850
I'm using a comprehension to create a dictionary. The error indicates that my key is stored as the value rather than the key.
Here is the full situation:
I have BLS data that looks like this:
O*NET-SOC Code Element ID Element Name Scale ID Data Value N Standard Error Lower CI Bound Upper CI Bound Recommend Suppress Not Relevant Date Domain Source
11-1011.00 1.A.1.a.1 Oral Comprehension IM 4.5 8 0.19 4.13 4.87 N n/a Jun-06 Analyst
11-1011.00 1.A.1.a.1 Oral Comprehension LV 4.75 8 0.25 4.26 5.24 N N Jun-06 Analyst
11-1011.00 1.A.1.a.2 Written Comprehension IM 4.38 8 0.18 4.02 4.73 N n/a Jun-06 Analyst
And would like to return a structure that looks like this, with detailed level data for every job (a job is represented by the SOC code, the left-most column of the data. For instance, the SOC code of the job 'clerk' below could be 11-1011.00).
{
'job':'clerk', 'description': 'works in a bank', 'abilities': {
'math': [
{
'Scale ID': 'IM',
'Data Value': 4.5,
'N' : 8,
'S_E': 0.19
},
{'Scale ID': 'LV',
'Data Value': 4.75,
'N': 8,
'S_E': 0.25
}
]
'english': [
{
'Scale ID': 'IM',
'Data Value': 2,
'N' : 8,
'S_E': 0.19
},
{'Scale ID': 'LV',
'Data Value': 3,
'N': 8,
'S_E': 0.25
}
]
}
},
To do this, I create a list of dictionaries in my abilities field, and for each ability, create a list of the level (LV) and importance (IM) data.
The error is flagged when I'm creating the dictionary for the IM / LV dictionaries.
Here's my code:
"""
Abilities
"""
# returns a list of dictionaries, each of the dictionaries representing a row in the data posted above with keys = top row and values = row vals.
abilities_m_l = create_abilities_master_list(file_list[0])
# for each job (for each dictionary in the master list of job dictionaries)
for job in d_l:
job_row = 1
while job_row < 100: # just to test
# initialize the list of abilities for the job
job['abilities'] = []
job['abilities'].append({abilities_m_l[job_row]['Element Name']:[]})
while job['O*NET-SOC Code'] == abilities_m_l[job_row]['O*NET-SOC Code']:
if abilities_m_l[job_row]['Element Name'] == abilities_m_l[job_row-1]['Element Name']:
job[abilities_m_l[job_row]['Element Name']].append({key:value for key,value in abilities_m_l[job_row] if key not in ('O*NET-SOC Code','Element Name', 'Scale ID')})
else:
job[abilities_m_l[job_row]['Element Name']] = []
job[abilities_m_l[job_row]['Element Name']].append({key:value for key,value in abilities_m_l[job_row] if key not in ('O*NET-SOC Code','Element Name', 'Scale ID')})
job_row += 1
break
for job in d_l:
print job['abilities']
Here is my error:
Traceback (most recent call last):
File "/private/var/folders/jv/9_sy0bn10mbdft1bk9t14qz40000gn/T/Cleanup At Startup/bls-397147690.633.py", line 65, in <module>
job[abilities_m_l[job_row]['Element Name']].append({key:value for key,value in abilities_m_l[job_row] if key not in ('O*NET-SOC Code','Element Name', 'Scale ID')})
KeyError: 'Oral Comprehension'
logout
Upvotes: 0
Views: 95
Reputation: 1121864
You are testing for the presence of the list incorrectly:
if abilities_m_l[job_row]['Element Name'] == abilities_m_l[job_row-1]['Element Name']:
job[abilities_m_l[job_row]['Element Name']].append({key:value for key,value in abilities_m_l[job_row] if key not in ('O*NET-SOC Code','Element Name', 'Scale ID')})
Here you assume that just because the previous row had the same element name, you will have already added a list for that key. Apparently that assumption is wrong for the Oral Comprehension
key.
Just test for the key:
key = abilities_m_l[job_row]['Element Name']
if key not in job:
job[key] = []
job[key].append({key:value for key,value in abilities_m_l[job_row] if key not in ('O*NET-SOC Code','Element Name', 'Scale ID')})
You can also use dict.setdefault()
to have it return the list value, or set an empty list value if the key is not yet set:
key = abilities_m_l[job_row]['Element Name']
job.setdefault(key, []).append({key:value for key,value in abilities_m_l[job_row] if key not in ('O*NET-SOC Code','Element Name', 'Scale ID')})
Upvotes: 1
Reputation: 2167
You cannot use .append() append to a non-existent key.
Consider using collections.defaultdict (so that non-existent keys default to using a list for their value), or initializing abilities_m_l[job_row]['Element Name'], or 'job' with a list. One of them is trying to append to a non-existent key (if the key doesn't already exist, you get the KeyError back)
Start with:
from collections import defaultdict
job=defaultdict(list)
That will ensure that keys default to the empty list, and allow your code to work.
Upvotes: 1