increment value in dictionary based on key in another dictionary - python

I have a masterDict dictionary with keys "1" through "8" with values set to 0
{'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0}
I also have anotherDict that i'm using to find the key containing a value closest to another value (i'm doing this multiple times with different values).
An example of one of those other values would be value1 = 900
An example of anotherDict would be:
{'1': 74, '2': 938, '3': 28, '4': 10, '5': 100, '6': 33, '7': 45, '8': 99}
The code i'm using to find the value closest to value1 in anotherDict is:
closestValue1 = key, value = min(anotherDict.items(), key=lambda (_, v): abs(v - value1))
In this case, closestValue1 returns:
{'2': 938}
How do I take this and increment the key 2 value in masterDict by 1?
So, masterDict would then contain:
{'1': 0, '2': 1, '3': 0, '4': 0, '5': 0, '6':0, '7':0, '8': 0}

master_dict = {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0}
another_dict = {'1': 74, '2': 938, '3': 28, '4': 10, '5': 100, '6': 33, '7': 45, '8': 99}
target_val = 900
target_key, _ = min(another_dict.items(), key=lambda x: abs(target_value-x[1]))
master_dict[target_key]+=1
print (master_dict)

Related

How to create a dictionary of permutation values?

I need to assign 0 and 1 as values to keys in the dictionaries:
combinations_string_list = [num_list_to_str(i) for i in itertools.product([0, 1], repeat=2)]
all_stategy = []
for i in range(16):
strategy_table = {x: y for x in combinations_string_list for y in [0, 1]}
all_stategy.append(strategy_table)
print(all_stategy)
I got [{'00': 1, '01': 1, '10': 1, '11': 1}, {'00': 1, '01': 1, '10': 1, '11': 1}, {'00': 1, '01': 1, '10': 1, '11': 1}, ...]
but I need [{'00': 0, '01': 0, '10': 0, '11': 0}, {'00': 0, '01': 0, '10': 0, '11': 1}, {'00': 0, '01': 0, '10': 1, '11': 0}, ...] instead.
How can I create this kind of value? Thanks!
You can zip the key sequence ["0", "1"] with each element of the cartesian product to produce input to dict:
>>> [dict(zip(["0", "1"], x)) for x in product([0,1], repeat=2)]
[{'0': 0, '1': 0}, {'0': 0, '1': 1}, {'0': 1, '1': 0}, {'0': 1, '1': 1}]
or
>>> values=[0,1]
>>> [dict(zip(map(str, values), x)) for x in product(values, repeat=2)]

Sum the values of dictionaries inside a list where the keys are the same

I have 4 lists of dictionaries and each list contains 4 dictionaries. The lists look similar to this:
A = [
{'1': 150, '2': 160, '3': 140, '4': 110},
{'1': 230, '2': 650, '3': 134, '4': 650},
{'1': 220, '2': 530, '3': 980, '4': 3450},
{'1': 150, '2': 160, '3': 440, '4': 110}]
B = [
{'1': 165, '2': 430, '3': 134, '4': 650},
{'1': 64, '2': 650, '3': 345, '4': 340},
{'1': 220, '2': 650, '3': 340, '4': 134},
{'1': 150, '2': 160, '3': 234, '4': 2340}]
C = [
{'1': 678, '2': 430, '3': 134, '4': 650},
{'1': 344, '2': 650, '3': 345, '4': 340},
{'1': 220, '2': 650, '3': 340, '4': 134},
{'1': 150, '2': 160, '3': 234, '4': 2340}]
D = [
{'1': 165, '2': 430, '3': 134, '4': 650},
{'1': 64, '2': 650, '3': 345, '4': 340},
{'1': 220, '2': 650, '3': 340, '4': 134},
{'1': 150, '2': 160, '3': 234, '4': 1440}]
I would like to sum the values of the first dictionary of each list, where the keys are the same (so for key '1', then for '2', then for '3' and so on ...), together with the values of the first dictionary of the rest of the lists.
Then do the same for the second, third and fourth dictionary.
The expected outcome should be 4 dictionaries, that maintain the order of the keys while summing up the values for the keys that are the same.
I have tried the piece of code below:
for i in range (4):
dict1 = A[i]
dict2 = B[i]
dict3 = C[i]
dict4 = D[i]
# adding the values with common key
Cdict = Counter(dict1) + Counter(dict2) + Counter(dict3) + Counter(dict4)
print(Cdict)
But the problem is that the order of the keys is changing:
Counter({'4': 2060, '2': 1450, '1': 1158, '3': 542})
Counter({'2': 2600, '4': 1670, '3': 1169, '1': 702})
Counter({'4': 3852, '2': 2480,'3': 2000, '1': 880})
Counter({'4': 6230, '3': 1142, '2': 640, '1': 600})
IIUC this is pretty straight forward. You just write a function to sum up all values per key. Then apply it to the transposed list of lists of dicts.
def sum_by_key(dicts):
result = {}
for d in dicts:
for k, v in d.items():
result[k] = result.get(k, 0) + v
return result
lists_of_dicts = [[{1:2, 3:4}, {1:10, 2:9}], [{3:8, 2:4}, {3:1, 2:5}]]
result = [sum_by_key(dicts) for dicts in zip(*lists_of_dicts)]
print(result)
(lists_of_dicts would be [A, B, C, D] with your variables)
Output:
[{1: 2, 3: 12, 2: 4}, {1: 10, 2: 14, 3: 1}]
edit: with your new sample data
lists_of_dicts = [A, B, C, D]
result = [sum_by_key(dicts) for dicts in zip(*lists_of_dicts)]
print(result)
produces
[{'1': 1158, '2': 1450, '3': 542, '4': 2060}, {'1': 702, '2': 2600, '3': 1169, '4': 1670}, {'1': 880, '2': 2480, '3': 2000, '4': 3852}, {'1': 600, '2': 640, '3': 1142, '4': 6230}]
I use numpy. And btw, I think the result you gave is incorrect, mine from the code below is:
results:
{'1': 1158, '2': 1450, '3': 542, '4': 2060}
{'1': 702, '2': 2600, '3': 1169, '4': 1670}
{'1': 880, '2': 2480, '3': 2000, '4': 3852}
{'1': 600, '2': 640, '3': 1142, '4': 6230}
import numpy as np
A = [
{'1': 150, '2': 160, '3': 140, '4': 110},
{'1': 230, '2': 650, '3': 134, '4': 650},
{'1': 220, '2': 530, '3': 980, '4': 3450},
{'1': 150, '2': 160, '3': 440, '4': 110}]
B = [
{'1': 165, '2': 430, '3': 134, '4': 650},
{'1': 64, '2': 650, '3': 345, '4': 340},
{'1': 220, '2': 650, '3': 340, '4': 134},
{'1': 150, '2': 160, '3': 234, '4': 2340}]
C = [
{'1': 678, '2': 430, '3': 134, '4': 650},
{'1': 344, '2': 650, '3': 345, '4': 340},
{'1': 220, '2': 650, '3': 340, '4': 134},
{'1': 150, '2': 160, '3': 234, '4': 2340}]
D = [
{'1': 165, '2': 430, '3': 134, '4': 650},
{'1': 64, '2': 650, '3': 345, '4': 340},
{'1': 220, '2': 650, '3': 340, '4': 134},
{'1': 150, '2': 160, '3': 234, '4': 1440}]
group_list = [A,B,C,D]
items_num = len(A)
results = []
for i in range(items_num):
cur_item_dict = dict()
for key in A[0].keys():
cur_item_dict[key] = np.sum([ls[i][key] for j, ls in enumerate(group_list)])
results.append(cur_item_dict)
print('results:')
for res in results:
print(res)

3 level nested dictionary comprehension in Python

I have a Python dictionary as follows:
d = {'1': {'1': 3, '2': 1, '3': 1, '4': 4, '5': 2, '6': 3},
'2': {'1': 3, '2': 3, '3': 1, '4': 2},
'3': {'1': 1, '2': 1, '3': 3, '4': 2, '5': 1, '6': 1, '7': 1},
'4': {'1': 1, '2': 1, '3': 3, '4': 2, '5': 1, '6': 1, '7': 1}}
I have this operation on the dictionary:
D = {}
for ko, vo in d.items():
for ki, vi in vo.items():
for i in range(vi):
D[f'{ko}_{ki}_{i}'] = someFunc(ko, ki, i)
I want to translate it into a one liner with dictionary comprehension as follows:
D = {f'{ko}_{ki}_{i}': someFunc(ko, ki, i) for i in range(vi) for ki, vi in vo.items() for ko, vo in d.items()}
But I get an error
NameError: name 'vi' is not defined
Can someone help me with the correct syntax for achieving this?
The order of the loops has to be reversed.
This is what you're looking for:
D = {f'{ko}_{ki}_{i}': someFunc(ko, ki, i) for ko, vo in d.items() for ki, vi in vo.items() for i in range(vi) }
The for clauses in the list comprehension should appear in the same order as in the equivalent for-loop code. The only thing that "moves" is that the innermost assignment is replaced by an expression at the beginning.
Please see https://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/ for details.

Convert text file to a dictionary of key strings and value integers

i have a text file of numbers like so
text.file
'1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9
i would like to convert this to an array like so :
myary= {'1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
but i want the keys to be a string and the values to be integer
i think i am able to get all of this as a string but that is not what i want
i want it to be seprate
using ast.literal_eval
import ast
txt = "'1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9"
print (ast.literal_eval('{' + txt + '}'))
#{'1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
If you don't want to use literal_eval
str="'1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9"
print({x[0].replace("'", ""):int(x[1]) for x in [y.split(': ') for y in [z for z in str.split(',')]] })
#{'2': 2, '7': 7, '8': 8, '4': 4, '1': 1, '9': 9, '3': 3, '6': 6, '5': 5}

How to make a nice matrix from a dictionary

I would like to make a matrix that makes a list of nested dictionaries.
But I can't find out how to make a matrix, end even less how to put my values into it.
My dictionary looks like:
{'1': {'3': 0, '2': 1, '5': 1, '4': 0, '6': 29},
'3': {'1': 0, '2': 0, '5': 0, '4': 1, '6': 1},
'2': {'1': 13, '3': 1, '5': 21, '4': 0, '6': 0},
'5': {'1': 39, '3': 0, '2': 1, '4': 0, '6': 14},
'4': {'1': 1, '3': 1, '2': 17, '5': 2, '6': 0},
'6': {'1': 0, '3': 43, '2': 0, '5': 0, '4': 1}}
and it should be ordered in a matrix so it looks like this:
1 2 3 4 5 6
1 - 1 0 0 1 29
2 13 - 1 0 21 0
3 0 0 - 1 0 1
4 1 17 1 - 2 0
5 39 1 0 0 - 14
6 0 0 43 1 0 -
I have only tried to understand how to make a matrix:
table=[[for 0 in range(6)] for j in range[6]]
print table
for d1 in range(6):
for d2 in range(6):
table[d1][d2]=d1+d2+2
print table
But I have a dictionary, not lists. I am really lost.
importpandasas pd
a = pd.DataFrame({'1': {'3': 0, '2': 1, '5': 1, '4': 0, '6': 29},
'3': {'1': 0, '2': 0, '5': 0, '4': 1, '6': 1},
'2': {'1': 13, '3': 1, '5': 21, '4': 0, '6': 0},
'5': {'1': 39, '3': 0, '2': 1, '4': 0, '6': 14},
'4': {'1': 1, '3': 1, '2': 17, '5': 2, '6': 0},
'6': {'1': 0, '3': 43, '2': 0, '5': 0, '4': 1}})
puts into a:
1 2 3 4 5 6
1 NaN 13 0 1 39 0
2 1 NaN 0 17 1 0
3 0 1 NaN 1 0 43
4 0 0 1 NaN 0 1
5 1 21 0 2 NaN 0
6 29 0 1 0 14 NaN
which can be then printed into your format:
print a.to_string(na_rep='-')
printing:
1 2 3 4 5 6
1 - 1 0 0 1 29
2 13 - 1 0 21 0
3 0 0 - 1 0 1
4 1 17 1 - 2 0
5 39 1 0 0 - 14
6 0 0 43 1 0 -
Using str.format():
dic = {'1': {'3': 0, '2': 1, '5': 1, '4': 0, '6': 29},
'3': {'1': 0, '2': 0, '5': 0, '4': 1, '6': 1},
'2': {'1': 13, '3': 1, '5': 21, '4': 0, '6': 0},
'5': {'1': 39, '3': 0, '2': 1, '4': 0, '6': 14},
'4': {'1': 1, '3': 1, '2': 17, '5': 2, '6': 0},
'6': {'1': 0, '3': 43, '2': 0, '5': 0, '4': 1}}
strs = "{0:^2} {1:^2} {2:^2} {3:^2} {4:^2} {5:^2} {6:^2}"
print strs.format(" ", *sorted(dic))
for x in sorted(dic):
print strs.format(x, *(dic[x].get(y, '-') for y in sorted(dic)))
output:
1 2 3 4 5 6
1 - 1 0 0 1 29
2 13 - 1 0 21 0
3 0 0 - 1 0 1
4 1 17 1 - 2 0
5 39 1 0 0 - 14
6 0 0 43 1 0 -
You can also generate the strs like this :
strs = " ".join("{"+"{0}{1}".format(i, ":^2}") for i in range(7))
This works for me. It's not very pythonic, as I don't use list comprehensions and that kind of stuff, but this way is easier to read and understand:
import sys
matrix = {'1': {'3': 0, '2': 1, '5': 1, '4': 0, '6': 29},
'3': {'1': 0, '2': 0, '5': 0, '4': 1, '6': 1},
'2': {'1': 13, '3': 1, '5': 21, '4': 0, '6': 0},
'5': {'1': 39, '3': 0, '2': 1, '4': 0, '6': 14},
'4': {'1': 1, '3': 1, '2': 17, '5': 2, '6': 0},
'6': {'1': 0, '3': 43, '2': 0, '5': 0, '4': 1}}
#print the column index
sys.stdout.write ("\t") # empty tab at the beginning
for col_index in range (1, len(matrix)+1):
sys.stdout.write ("%d\t" % col_index)
print ""
# order the matrix rows, using the dictionary keys
for row_index in sorted (matrix.iterkeys()):
#print the row index
sys.stdout.write (str(row_index)+"\t")
# take each row, and order it by its inner key:
row = matrix[row_index]
ordered_row = sorted (row.iterkeys())
# iterate from 1 to number_of_matrix_rows
for col_index in range (1, len(matrix)+1):
# if the current column exists as a key in
# the row, print it. Otherwise, print "-"
row_item = "-"
if str(col_index) in ordered_row:
row_item = row[str(col_index)]
sys.stdout.write (str(row_item)+"\t")
# print next row
print ""
Here is the python code which will print the matrix on screen. Call prettyPrint(data).
table is a multidimentional array(matrix) with the data.
import string
data = {'1': {'3': 0, '2': 1, '5': 1, '4': 0, '6': 29},
'3': {'1': 0, '2': 0, '5': 0, '4': 1, '6': 1},
'2': {'1': 13, '3': 1, '5': 21, '4': 0, '6': 0},
'5': {'1': 39, '3': 0, '2': 1, '4': 0, '6': 14},
'4': {'1': 1, '3': 1, '2': 17, '5': 2, '6': 0},
'6': {'1': 0, '3': 43, '2': 0, '5': 0, '4': 1}}
def prettyPrint(data):
count = len(data)
table = [[0 for x in xrange(count)] for x in xrange(count)]
print string.ljust(' ', 4),
for j in range(1, count + 1):
print string.ljust(`j`, 4),
print ""
for i in range(1, count + 1):
print string.ljust(`i`, 4),
for j in range(1, count + 1):
#print string.rjust(`j`, 4),
if j != i:
print string.ljust(`data[str(i)][str(j)]`, 4),
table[i-1][j-1] = data[str(i)][str(j)]
else:S
print string.ljust('-', 4),
table[i-1][j-1] = '-'
print ""
print "\nMatrix: \n"
for row in table:
print row
prettyPrint(data)
Output:
>>>
1 2 3 4 5 6
1 - 1 0 0 1 29
2 13 - 1 0 21 0
3 0 0 - 1 0 1
4 1 17 1 - 2 0
5 39 1 0 0 - 14
6 0 0 43 1 0 -
Matrix:
[0, 1, 0, 0, 1, 29]
[13, 0, 1, 0, 21, 0]
[0, 0, 0, 1, 0, 1]
[1, 17, 1, 0, 2, 0]
[39, 1, 0, 0, 0, 14]
[0, 0, 43, 1, 0, 0]
>>>
A function based on #Ashwini Chaudhary's solution using str.format that can take a dict with variable lenght:
def prettyPrint(d,space=5,fill='-'):
strs = ''.join('{{{0}:^{1}}}'.format(str(i),str(space))
for i in xrange(len(d)+1))
std = sorted(d)
print strs.format(" ",*std)
for x in std:
print strs.format(x,*(d[x].get(y,fill) for y in std))
prettyPrint(d)
OUT:
1 2 3 4 5 6
1 - 1 0 0 1 29
2 13 - 1 0 21 0
3 0 0 - 1 0 1
4 1 17 1 - 2 0
5 39 1 0 0 - 14
6 0 0 43 1 0 -
OR:
prettyPrint(d,space=3,fill='0')
OUT:
1 2 3 4 5 6
1 0 1 0 0 1 29
2 13 0 1 0 21 0
3 0 0 0 1 0 1
4 1 17 1 0 2 0
5 39 1 0 0 0 14
6 0 0 43 1 0 0
Probably not a perfect or most effective solution, but it works:
def printMatrix (d):
# get the amount of characters needed for the maximum number
numberWidth = len(str(max(max(v.values()) for v in d.values())))
# function to format the numbers
formatNumber = lambda x: str(x).rjust(numberWidth)
keys = sorted(d.keys())
rows = [' '.join(map(formatNumber, [''] + keys))]
for r in keys:
row = [r]
for k in keys:
row.append(d[r].get(k, '-'))
rows.append(' '.join(map(formatNumber, row)))
print('\n'.join(rows))
Used like this:
>>> d = { ... }
>>> printMatrix(d)
1 2 3 4 5 6
1 - 1 0 0 1 29
2 13 - 1 0 21 0
3 0 0 - 1 0 1
4 1 17 1 - 2 0
5 39 1 0 0 - 14
6 0 0 43 1 0 -
The following one-liner can change your dictionary to a list of list(square matrix):
[[d[str(i)].get(str(j), '-') for j in range(1, 7)] for i in range(1, 7)]
where d is your input dictionary. Based upon that, it's easy to print in any format you desire. BTW, unless this is a school assignment, I don't think printing in any concrete format really matters. Changing dictionary to matrix-like data structure makes more sense. If just for debug's sake, you can use pprint to get a nicer output.
Here is a verbose and flexible code without external libraries, it also returns an usable matrix.
dict_matrix = {'1': {'3': 0, '2': 1, '5': 1, '4': 0, '6': 29},
'3': {'1': 0, '2': 0, '5': 0, '4': 1, '6': 1},
'2': {'1': 13, '3': 1, '5': 21, '4': 0, '6': 0},
'5': {'1': 39, '3': 0, '2': 1, '4': 0, '6': 14},
'4': {'1': 1, '3': 1, '2': 17, '5': 2, '6': 0},
'6': {'1': 0, '3': 43, '2': 0, '5': 0, '4': 1}}
def matricize_dict(a_dict, x_size, y_size):
matrix = []
for i in range(y_size):
line = []
for j in range(x_size):
line.append('-')
matrix.append(line)
for i in range(y_size):
line = dict_matrix[str(i+1)]
for j in range(x_size):
try:
cell = line[str(j+1)]
except KeyError:
pass
else:
matrix[i][j] = cell
for item in matrix:
print(item)
return matrix
matricize_dict(dict_matrix, 6, 6)

Categories