Rename subkeys of nested dictionary dynamically My nested (ordered) dictionary looks like this:

OrderedDict([
    ('1', OrderedDict([('1994_fte_count', '4'), ('1995_fte_count', '2'), ('1996_fte_count', '5'), ('1997_fte_count', '7')])),
    ('2', OrderedDict([('1994_fte_count', '5'), ('1995_fte_count', '22'), ('1996_fte_count', '6'), ('1997_fte_count', '3')])),
    ('3', OrderedDict([('1994_fte_count', '6'), ('1995_fte_count', '7'), ('1996_fte_count', '7'), ('1997_fte_count', '81')]))
    ])


The subkeys ("1994_fte_count", "1995_fte_count", etc.) all range up until 2000. I want to replace the year with the difference to a given year. This shall happen dynamically for a lot of years. For example, I start with 1995, and "1995_fte_count" shall be renamed "lag0_fte_count", while "1994_fte_count" shall be renamed "lag1_fte_count". I read the file in a several times, each time with a different benchmark year.

I currently use the following nested loop:

year = "1996" # comes as string
lag_length = 2
year_range = range(int(year)-lag_length, int(year))
replacement = ["lag" + str(i) for i in reversed(range(0,lag_length))]
for ID in my_dict.keys():
    for subkey in my_dict[ID].keys():
        for i in range(0, len(year_range)):
            acutal_year = str(year_range[i])
            if subkey.startswith(acutal_year):
                newkey = subkey.replace(acutal_year, replacement[i])
                my_dict[ID][newkey] = my_dict[ID].pop(subkey)


Given the nature of the task (simple text replace), I do think that there must be a shorter, more readable and faster way than to iterate over all the subkeys multiple times. Who knows how to?
Clarity probably trumps speed, but then again, it's not quite clear
why you need this format and what is further going to happen to that
dictionary.

You can definitely get rid of the innermost loop by computing the
replacement index on the fly instead of testing all possibilities:

from collections import OrderedDict

year = int("1996") # comes as string
lag_length = 2
replacement = ["lag%s_fte_count" % (i - 1) for i in range(lag_length, 0, -1)]

for ID, value in my_dict.iteritems():
    for subkey in value.keys():
        year_string = subkey[:4]

        if not year_string.isdigit():
            continue

        parsed_year = int(year_string)

        if not year - lag_length &lt;= parsed_year &lt; year:
            continue

        value[replacement[lag_length + parsed_year - year]] = value.pop(subkey)


I also used iteritems to get both values at the same time; for
value.keys() that's sadly not possible while iterating.  The year
input should also be parsed immediately as it'll always be used in the
integer form.

Next I'm assuming the keys start with the four-character year, so then
the year can be parsed and compared with the target range and if it's in
the range, the key is renamed by calculating the correct index.

Furthermore you could remove the isdigit call if the format allows for
it and replacement could be removed by always generating the string
immediately, e.g. like this:

value["lag%s_fte_count" % (year - parsed_year - 1)] = value.pop(subkey)