Calculating min difference between two dictionaries - python

I'm trying to calculate difference between two dictionaries to return a specific value.
I've entered different values which should return different results, but the result remains unchanged.
diets = {"normal" : {'p': '32.50', 'c': '60', 'f': '40.86'},
"oncology" : {'p': '35', 'c': '52.50', 'f': '37.63'},
"cardiology" : {'p': '32.50', 'c': '30', 'f': '26.88'},
"diabetes" : {'p': '20', 'c': '27.50', 'f': '27.95'},
"kidney" : {'p': '15', 'c': '55', 'f': '23.65'}}
amounts = {'p': p, 'c': c, 'f': f}
value = { k : diets[k] for k in set(diets) - set(amounts) }
calculate_error = min(value)
print(calculate_error)
When i input 32, 60 and 40, the returned result should be normal, but oncology is returned instead

You should look at the values you are creating when you do this:
set(diets)
This is just a list of keys.
{'cardiology', 'diabetes', 'kidney', 'normal', 'oncology'}
When you subtract the other list of keys, you just get the original list because no values are in common.
You need to actually step through the items and do the subtraction to get the differences. Then you can find the sum of the diffs and the min of that sum.
One way would be:
diets = {"normal" : {'p': '32.50', 'c': '60', 'f': '40.86'},
"oncology" : {'p': '35', 'c': '52.50', 'f': '37.63'},
"cardiology" : {'p': '32.50', 'c': '30', 'f': '26.88'},
"diabetes" : {'p': '20', 'c': '27.50', 'f': '27.95'},
"kidney" : {'p': '15', 'c': '55', 'f': '23.65'}}
amounts = {'p': 32., 'c': 60., 'f': 40.}
mins = [(diet, sum([abs(amounts[k] - float(d[k])) for k in amounts])) for diet, d in diets.items()]
the_min = min(mins, key = lambda x: x[1])
mins will be:
[('normal', 1.3599999999999994),
('oncology', 12.869999999999997),
('cardiology', 43.620000000000005),
('diabetes', 56.55),
('kidney', 38.35)]
the_min will be:
('normal', 1.3599999999999994)

It looks you totally confused what value would be
>>> diets = {"normal" : {'p':'32.50', 'c':'60', 'f':'40.86'},
... "oncology" : {'p':'35', 'c':'52.50', 'f':'37.63'},
... "cardiology" : {'p':'32.50', 'c':'30', 'f':'26.88'},
... "diabetes" : {'p':'20', 'c':'27.50', 'f':'27.95'},
... "kidney" : {'p':'15', 'c':'55', 'f':'23.65'}}
>>> set(diets)
{'kidney', 'cardiology', 'oncology', 'normal', 'diabetes'}
>>> amounts = {'p':32, 'c':60, 'f':40}
>>> set(amounts)
{'c', 'f', 'p'}
>>> set(diets) - set(amounts)
{'cardiology', 'diabetes', 'kidney', 'oncology', 'normal'}
>>> value = { k : diets[k] for k in set(diets) - set(amounts) }
>>> value
{'cardiology': {'p': '32.50', 'c': '30', 'f': '26.88'},
'diabetes': {'p': '20', 'c': '27.50', 'f': '27.95'},
'kidney': {'p': '15', 'c': '55', 'f': '23.65'},
'oncology': {'p': '35', 'c': '52.50', 'f': '37.63'},
'normal': {'p': '32.50', 'c': '60', 'f': '40.86'}}
>>> min(value)
'cardiology'
that said I would expect that you to get cardiology, i.e. the min from diets.keys()
That said, note that the values in the diets are str, e.g. '32.50', You will need to convert these before any calculations.

Related

How can i make a dictionary from txt file in python

I have get this txt file
A:{A:0, B:6, C:4, D:3, E:0, F:0, G:0}
B:{A:6, B:0, C:2, D:0, E:4, F:0, G:0}
C:{A:4, B:2, C:0, D:2, E:0, F:8, G:0}
D:{A:3, B:0, C:2, D:0, E:3, F:0, G:0}
E:{A:0, B:4, C:0, D:3, E:0, F:7, G:6}
F:{A:0, B:0, C:8, D:0, E:7, F:0, G:6}
G:{A:0, B:0, C:0, D:0, E:6, F:6, G:0}
titles = []
with open("graph.txt", "r") as file:
for line in file:
column=line.split(":")
title=column[0]
titles.append(title)
i need to make dictionaries for each title which i got like A,B,C
Format each line properly and you can use ast.literal_eval. I used regex to find each key and replace it with the same key surrounded by quotes.
import ast
import re
KEY_PATTERN = re.compile(r'(\w+?):')
dics = []
with open('graph.txt') as f:
for line in f:
line = line.strip()
if line:
dic_str = "{" + KEY_PATTERN.sub(r'"\g<1>":', line) + "}"
dics.append(ast.literal_eval(dic_str))
print(dics)
Can be shorter (though harder to read):
import ast
import re
KEY_PATTERN = re.compile(r'(\w+?):')
with open('graph.txt') as f:
dics = [ast.literal_eval("{" + KEY_PATTERN.sub(r'"\g<1>":', line) + "}") for line in f if line.strip()]
print(dics)
Output:
[{'A': {'A': 0, 'B': 6, 'C': 4, 'D': 3, 'E': 0, 'F': 0, 'G': 0}}, {'B': {'A': 6, 'B': 0, 'C': 2, 'D': 0, 'E': 4, 'F': 0, 'G': 0}}, {'C': {'A': 4, 'B': 2, 'C': 0, 'D': 2, 'E': 0, 'F': 8, 'G': 0}}, {'D': {'A': 3, 'B': 0, 'C': 2, 'D': 0, 'E':3, 'F': 0, 'G': 0}}, {'E': {'A': 0, 'B': 4, 'C': 0, 'D': 3, 'E': 0, 'F': 7, 'G': 6}}, {'F': {'A': 0, 'B': 0, 'C': 8, 'D': 0, 'E': 7, 'F': 0, 'G': 6}}, {'G': {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 6, 'F': 6, 'G': 0}}]
If you want the result to be just one dict than change:
dics = []
# and
dics.append(ast.literal_eval(dic_str))
to
dics = {}
# and
dics.update(ast.literal_eval(dic_str))
This can be achieved with the following sample:
import re
titles = []
with open("graph.txt", "r") as file:
for line in file:
if ':' in line:
title=re.match(r"^(.*?):", line).groups()[0]
dict_str= re.match("^.*?\{(.*?)\}", line).groups()[0]
dictionary = {key:value for (key,value) in (item.strip().split(':') for item in dict_str.split(','))}
titles.append({title: dictionary})
for item in titles:
print(item)
This will produce output like:
{'A': {'A': '0', 'C': '4', 'B': '6', 'E': '0', 'D': '3', 'G': '0', 'F': '0'}}
{'B': {'A': '6', 'C': '2', 'B': '0', 'E': '4', 'D': '0', 'G': '0', 'F': '0'}}
{'C': {'A': '4', 'C': '0', 'B': '2', 'E': '0', 'D': '2', 'G': '0', 'F': '8'}}
{'D': {'A': '3', 'C': '2', 'B': '0', 'E': '3', 'D': '0', 'G': '0', 'F': '0'}}
{'E': {'A': '0', 'C': '0', 'B': '4', 'E': '0', 'D': '3', 'G': '6', 'F': '7'}}
{'F': {'A': '0', 'C': '8', 'B': '0', 'E': '7', 'D': '0', 'G': '6', 'F': '0'}}
{'G': {'A': '0', 'C': '0', 'B': '0', 'E': '6', 'D': '0', 'G': '0', 'F': '6'}}

Append dictionary in a for loop [duplicate]

This question already has answers here:
How to merge dicts, collecting values from matching keys?
(17 answers)
Closed 3 years ago.
I would like to append dictionary in a for loop such that i get a concatenated dictionary. Also, it is not necessary that keys of all dictionary will be exactly same.
For eq
one={'a': '2', 'c': 't', 'b': '4'}
two={'a': '3.4', 'c': '7.6'}
three={'a': 1.2, 'c': 3.4, 'd': '2.3'}
Output:
combined={'a':['2','3.4','1.2'],'b':'4','c':['t','7.6','3.4'],
'd':'2.3'}
Now coming to original question:
Every time a for loop iterates, a dictionary will be generated and i would like to append it.
Something like:
emptydict={}
for x in z:
newdict=x.dict()
emptydict.append(newdict)
print(emptydict)
try this
one={'a': '2', 'c': 't', 'b': '4'}
two={'a': '3.4', 'c': '7.6'}
three={'a': 1.2, 'c': 3.4, 'd': '2.3'}
df = pd.DataFrame([one,two,three])
a b c d
0 2 4 t NaN
1 3.4 NaN 7.6 NaN
2 1.2 NaN 3.4 2.3
df.to_dict(orient='list')
Output
{'a': ['2', '3.4', 1.2],
'b': ['4', nan, nan],
'c': ['t', '7.6', 3.4],
'd': [nan, nan, '2.3']}
You can try something like this.
one = {'a': '2', 'c': 't', 'b': '4'}
two = {'a': '3.4', 'c': '7.6'}
three = {'a': 1.2, 'c': 3.4, 'd': '2.3'}
new_dict = {}
list_dict = [one, two, three]
for d in list_dict:
for key in d:
if key not in new_dict:
new_dict[key] = []
new_dict[key].append(d[key])
print(new_dict)
Output : {'a': ['2', '3.4', 1.2], 'c': ['t', '7.6', 3.4], 'b': ['4'], 'd': ['2.3']}
I have used your examples to do so -
one = {'a': '2', 'c': 't', 'b': '4'}
two = {'a': '3.4', 'c': '7.6'}
three = {'a': 1.2, 'c': 3.4, 'd': '2.3'}
dicts = [one, two, three]
for dictionary in dicts:
for key, value in dictionary.items():
try:
new[key].append(value)
except KeyError:
new[key] = [value]
O/P -
{'a': ['2', '3.4', 1.2], 'c': ['t', '7.6', 3.4], 'b': ['4'], 'd': ['2.3']}
You can try dict-comprehension and list-comprehension :
new_dict = {k : [j[k] for j in [one,two,three] if k in j] for k in set(list(one.keys())+list(two.keys())+list(three.keys())
# Output : { 'a': ['2', '3.4', 1.2], 'b': ['4'], 'c': ['t', '7.6', 3.4], 'd': ['2.3']}
If you want the keys with only one element as possible value not in the list then try this :
new_dict = a = {k : [j[k] for j in [one,two,three] if k in j][0] if len([j[k] for j in [one,two,three] if k in j]) ==1 else [j[k] for j in [one,two,three] if k in j] for k in set(list(one.keys())+list(two.keys())+list(three.keys()))}
# Output : {'a': ['2', '3.4', 1.2], 'b': '4', 'c': ['t', '7.6', 3.4], 'd': '2.3'}

Python accessing dictionary inside of dictionary returns distorted dict

I have recently been working on a python application that handles some sort of schedule. I have a dictionary that contains the number of days in a rotation in a schedule, and then each day contains a dictionary with each different part of the day. It looks like this:
schedule = {
'rotation': 6,
'1' : {'B': '8:32', 'C': '9:34', 'D' : '10:36', 'F':'12:11', 'G': '1:13', 'H':'2:15'},
'2' : {'A': '8:32', 'B': '9:34', 'C,' : '10:36', 'E':'12:11', 'F': '1:13', 'G,':'2:15'},
'3' : {'A': '8:32', 'B': '9:34', 'D,' : '10:36', 'E':'12:11', 'F': '1:13', 'H,':'2:15'},
'4' : {'A': '8:32', 'C': '9:34', 'D,' : '10:36', 'E':'12:11', 'G': '1:13', 'H,':'2:15'},
'5' : {'B' : '8:40', 'D' : '11:00', 'F' : '12:55', 'H' : '2:15' },
'6' : {'A' : '8:40', 'C' : '11:00', 'E' : '12:55', 'G' : '2:15' }
}
This all looks like it should work, yet when I print it out, I get a distorted dictionary that looks like it is sorted:
{'1': {'C': '9:34', 'B': '8:32', 'D': '10:36', 'G': '1:13', 'F': '12:11', 'H': '2:15'},
'3': {'A': '8:32', 'D,': '10:36', 'B': '9:34', 'E': '12:11', 'F': '1:13', 'H,': '2:15'},
'2': {'A': '8:32', 'B': '9:34', 'E': '12:11', 'F': '1:13', 'C,': '10:36', 'G,': '2:15'},
'5': {'H': '2:15', 'B': '8:40', 'D': '11:00', 'F': '12:55'},
'4': {'A': '8:32', 'C': '9:34', 'E': '12:11', 'G': '1:13', 'D,': '10:36', 'H,': '2:15'},
'6': {'A': '8:40', 'C': '11:00', 'E': '12:55', 'G': '2:15'},
'rotation': 6}
As you can see, in day 1, it starts with C instead of B when printing, and the 'rotation' is at the end of the dictionary instead of the front. Why does my dictionary print like this?
The order in a dictionary is not stable, due to the hash function. On top of this, Python now uses a salt value when hashing, meaning that the order will be different each run (except if you ask for a stable dict).
Python dictionary is not required to preserve order. If order is what you want then you could use lists. If you just want to view a dictionary in sorted order, you can use .sort() or sorted() to help you print.
You can sort this dictionary but you have to make an exception for rotation since its values do not fit the rest of the format of being a dictionary with alphabetical keys
d = {k: dict(sorted(v.items(), key=lambda x: x[0])) if k != 'rotation' else schedule[k] for k, v in schedule.items()}
print(d)
# {'rotation': 6, '1': {'B': '8:32', 'C': '9:34', 'D': '10:36', 'F': '12:11', 'G': '1:13', 'H': '2:15'}, '2': {'A': '8:32', 'B': '9:34', 'C,': '10:36', 'E': '12:11', 'F': '1:13', 'G,': '2:15'}, '3': {'A': '8:32', 'B': '9:34', 'D,': '10:36', 'E': '12:11', 'F': '1:13', 'H,': '2:15'}, '4': {'A': '8:32', 'C': '9:34', 'D,': '10:36', 'E': '12:11', 'G': '1:13', 'H,': '2:15'}, '5': {'B': '8:40', 'D': '11:00', 'F': '12:55', 'H': '2:15'}, '6': {'A': '8:40', 'C': '11:00', 'E': '12:55', 'G': '2:15'}}

Find biggest value in a python dict

I have a python dict like below:
{ '1': {'a': '0.6', 'b': '0.8', 'c': '2','d': '0.5'},
'2': {'a': '0.7', 'b': '0.9', 'c': '0.1','d': '0.2'},
'3': {'a': '0.5', 'b': '0.8', 'c': '3'},
}
How could I get the following result?
('2','a','0.7') ('2',b','0.9') ('3','c', '3') ('1','d', '0.5')
Well, here is the code for it (just 5 lines):
total = []
for i in ['a', 'b', 'c', 'd']:
kv = max(a.iterkeys(), key=(lambda key: float(a[key][i]) if i in a[key].keys() else -9.0))
hv = a[kv][i]
total.append((kv, i, hv))
print total
Output:
[('2', 'a', '0.7'), ('2', 'b', '0.9'), ('3', 'c', '3'), ('1', 'd', '0.5')]
-9.0 is just a random low number.
x={ '1': {'a': '0.6', 'b': '0.8', 'c': '2','d': '0.5'},
'2': {'a': '0.7', 'b': '0.9', 'c': '0.1','d': '0.2'},
'3': {'a': '0.5', 'b': '0.8', 'c': '3'},
}
d={}
for i,j in x.iteritems():
for k,m in j.iteritems():
d.setdefault(k,[0,0])
if j[k]>d[k][0]:
d[k]=(j[k],i)
print [(j[1],i,j[0]) for i,j in d.items()]
You can use additional dict to do your job.
Output:[('2', 'a', '0.7'), ('3', 'c', '3'), ('2', 'b', '0.9'), ('1', 'd', '0.5')]
I agree the question is a bit vague.. I recommend you dont use strings as values.. use int or float if you can in the dictionaries, also does not specify if python 2.x or 3.x
but I think you are after something like this..
def filter_dict(values):
result = collections.Counter()
for value in values.keys():
for k, v in values[value].items():
v = float(v)
result[k] = v if v > result[k] else result[k]
return result
this is how it behaves:
class FilterDictTest(unittest.TestCase):
def test_filter_dict(self):
# Arrange
actual = {
'1': {'a': '0.6', 'b': '0.8', 'c': '2', 'd': '0.5'},
'2': {'a': '0.7', 'b': '0.9', 'c': '0.1', 'd': '0.2'},
'3': {'a': '0.5', 'b': '0.8', 'c': '3'}
}
expected = {
'a': 0.7,
'b': 0.9,
'c': 3,
'd': 0.5
}
# Act & Assert
self.assertEquals(filter_dict(actual), expected)
A little late here.
#!/usr/bin/env python3.5
# entry
entry = {'1': {'a': '0.6', 'b': '0.8', 'c': '2','d': '0.5'}, '2': {'a': '0.7', 'b': '0.9', 'c': '0.1','d': '0.2'}, '3': {'a': '0.5', 'b': '0.8', 'c': '3'}}
# identify keys
all_categories = []
for number, dct in entry.items():
for key, val in dct.items():
all_categories = all_categories + list(dct.keys())
all_categories = set(all_categories)
# Get max values
max_values = {category:None for category in all_categories}
for category in all_categories:
for number, dct in entry.items():
if category in dct.keys():
if max_values[category] is None:
max_values[category] = (number, dct[category])
elif float(max_values[category][1]) < float(dct[category]):
max_values[category] = (number, dct[category])
output = [(number, category, value) for (category, (number, value)) in max_values.items()]
print (output)
Output:
[('2', 'a', '0.7'), ('1', 'd', '0.5'), ('2', 'b', '0.9'), ('3', 'c', '3')]
Not exactly in the order you expected them, but the values are correct. It's not the most elegant solution, though.
I iterate a second time in dict to compare values.
values = []
for key in d:
for skey in d[key]:
max = 0
_key_ = ''
for _ in d:
if d[_].has_key(skey):
if d[_][skey]>max:
max = d[_][skey]
_key_ = _
if (_key_, skey, max) not in values:
values.append((_key_, skey, max))
print values

Calculate values between two dicts in Python

I have two dict in python one of quantities and the other of prices the both have the same keys
What is the best, and quicks way to calculate Quantity * price for each element in the dict
Example
prices = {'a': '40', 'b': '40', 'c': '35'}
data ={'a': '1', 'b': '2', 'c': '4'}
I want to get a total sum (int) of 260
You can use sum over a generator expression like this:
sum(float(v)*float(prices[k]) for k,v in data.iteritems())
>>> prices = {'a': '40', 'b': '40', 'c': '35'}
>>> data ={'a': '1', 'b': '2', 'c': '4'}
>>> sum(int(prices[x])*int(data[x]) for x in data)
260

Categories

Resources