How do I combine two dictionaries based on their values? - python

I currently have two dictionaries containing nucleotide strings as the key and their counts as the value.
example:
dict1 = {GGA:64231, GAT: 66582}
dict2 = {TCC:64231, ATC: 66582}
I want to make a new dictionary that looks like this:
dict3 = {'GGA:TCC':64231, 'GAT:ATC':66582}
How can I do this?

Simply swap the key/value pairs in the dictionary to build your new one (assuming you have unique values, and your dictionaries all have matching values):
Python 3:
dict1 = {'GGA':64231, 'GAT': 66582}
dict1 = {v:k for k,v in dict1.items()} # {66582: 'GAT', 64231: 'GGA'}
dict2 = {'TCC':64231, 'ATC': 66582}
dict2 = {v:k for k,v in dict2.items()} # {66582: 'ATC', 64231: 'TCC'}
dict3 = {"{}:{}".format(dict1[k],dict2[k]):k for k in dict1} # {'GGA:TCC': 64231, 'GAT:ATC': 66582}
Python 2.7 use iteritems() instead of items()

The way I would do that is using list comprehension, which I believe is more pythonic:
dict1 = {GGA:64231, GAT: 66582}
dict2 = {TCC:64231, ATC: 66582}
new_dict = { x+":"+y:dict1[x] for x in dict1.keys() for y in dict2.keys() if dict1[x] == dict2[y]}
And this is the output:
{'GGA:TCC': 64231, 'GAT:ATC': 66582}

i think it would be smarter to map them with the key as the numbers for example since they are the defining factor.
a={i:[w] for w,i in dict1.items()}
b={i:w if i not in a else a[i]+[w] for w,i in dict2.items()}
output
{64231: ['GGA', 'TCC'], 66582: ['GAT', 'ATC']}
or in your case
a={i:[w] for w,i in dict1.items()}
b={i:w if i not in a else ":".join(a[i]+[w]) for w,i in dict2.items()}
output
{64231: 'GGA:TCC', 66582: 'GAT:ATC'}

What a fun little problem. My version doesn't search the dict, it assumes your dicts have perfect information and the values can be sorted by the number value.
dict1 = {"GGA": 64231, "GAT": 66582}
dict2 = {"TCC": 64231, "ATC": 66582}
dict3 = {
"%s:%s" % (k, l): v
for (k, v), (l, b) in zip(
sorted(dict1.items(), key=lambda x: x[1]),
sorted(dict2.items(), key=lambda x: x[1]),
)
}
print(dict3)
I'll say though #TheoretiCAL's answer is likely the best.

One way may be to try using defaultdict:
from collections import defaultdict
dict1 = {'GGA':64231, 'GAT': 66582}
dict2 = {'TCC':64231, 'ATC': 66582}
result_dict = defaultdict(list)
# read first dictionary and add value as key and key to list of values
for k, v in dict1.items(): result_dict[v].append(k)
# read other dictionary and add value as key and key to list of values
for k, v in dict2.items(): result_dict[v].append(k)
# change key to value in dicitonary
result_dict = {':'.join(v):k for k, v in result_dict.items()}
print(result_dict)
Output:
{'GAT:ATC': 66582, 'GGA:TCC': 64231}

Related

How to return the values of dictionary key that has gained new values in a different dictionary

I have question a bit similar to:Replacing the value of a Python dictionary with the value of another dictionary that matches the other dictionaries key
However in my case I got two dictionaries
dict1 = {'foo' : ['val1' , 'val2' , 'val3'] , 'bar' : ['val4' , 'val5']}
dict2 = {'foo' : ['val2', 'val10', 'val11'] , 'bar' : ['val1' , 'val4']}
What I want to return is
dict3 = {'foo' : ['val10', 'val11'] , 'bar' : ['val1']}
and the opposite which is
dict4 = {'foo' : ['val1', 'val3'] , 'bar' : ['val5']}
where dict3 returns a dictionary of the values the keys 'foo' and 'bar' has gained in dict2 and the dict4 is a dictionary of the values the keys 'foo' and 'bar' has lost in dict2
One way I have tried solving this is to:
iterate over both dictionaries then
if key of dict1 == key of dict2
return the values of the key in dict1 and compare with the values in dict2
return the values that aren't in both
as a dictionary of the key and those values
This idea isn't working and obviously highly inefficient. I was hoping there is a more efficient working way to do this
Two dict comprehensions will do the trick:
dict3 = {k: [x for x in v if x not in dict1[k]] for k, v in dict2.items()}
print(dict3)
# {'foo': ['val10', 'val11'], 'bar': ['val1']}
dict4 = {k: [x for x in v if x not in dict2[k]] for k, v in dict1.items()}
print(dict4)
# {'foo': ['val1', 'val3'], 'bar': ['val5']}
The above two comprehensions basically filter out the values from key that don't exist in the other dictionary, which is done both ways.
You can also do this without dict comprehensions:
dict3 = {}
for k,v in dict2.items():
dict3[k] = [x for x in v if x not in dict1[k]]
print(dict3)
# {'foo': ['val10', 'val11'], 'bar': ['val1']}
dict4 = {}
for k,v in dict1.items():
dict4[k] = [x for x in v if x not in dict2[k]]
print(dict4)
# {'foo': ['val1', 'val3'], 'bar': ['val5']}

How to make in-place changes to values between two dictionaries provided the value in dictionary1 is the same as Key in dictionary2?

I have two dictionaries, the first is a dictionary of dictionaries.
dict = {k1:{kk1:vv1, kk2: vv2}, k2:{kkk1:vvv1, kkk2:vvv2}}
dict1 = dict['k2']
# So basically:
# dict1 = {kkk1:vvv1, kkk2:vvv2}
dict3 = {vvv1:actualv1, vvv2:actualv2}
I want the end result to be:
dict1 = {kkk1:actualv1, kkk2:actualv2}
Which is basically:
dict = {k1:{kk1:vv1, kk2: vv2}, k2:{kkk1:actualv1, kkk2:actualv2}}
So, I have tried dictionary comprehension:
{k: dict2.get(v, v) for k, v in dict1.items()}
But to no avail. I have tried to be as clear as possible. One more thing I'd like to mention is that The 'dict' contains about 400 k-v pairs. I have given an example of what I would like to achieve. Help.
Patching the dict1 alone and inplace, accordint to dict3, can be done like this:
d = dict(k1=dict(kk1='vv1', kk2='vv2'),
k2=dict(kkk1='vvv1', kkk2='vvv2'))
dict1 = d['k2']
dict3 = dict(vvv1='actualv1', vvv2='actualv2')
for k in dict1:
v = dict1[k]
try:
dict1[k] = dict3[v]
except KeyError:
pass
print d
prints:
{'k2': {'kkk2': 'actualv2', 'kkk1': 'actualv1'},
'k1': {'kk1': 'vv1', 'kk2': 'vv2'}}
You can try this:
dict = {'k1':{'kk1':'vv1', 'kk2': 'vv2'}, 'k2':{'kkk1':'vvv1', 'kkk2':'vvv2'}}
dict3 = {'vvv1':'actualv1', 'vvv2':'actualv2'}
final_data = {a:{c:dict3.get(d, d) for c, d in b.items()} for a, b in dict.items()}
Output:
{'k1': {'kk1': 'vv1', 'kk2': 'vv2'}, 'k2': {'kkk1': 'actualv1', 'kkk2': 'actualv2'}}
Ok, so you want to process a sub dict from a dict of dicts, given its key, and replace values according to a replacement dict original_value => replacement_value.
You can just do it:
def patch_dic(dic, key, dict3):
for k,v in dic[key].items(): # iterate the sub dict
for orig, repl in dict3.items(): # iterate the replacement dict
if v == orig: # if a value exists in the replacement dict
dic[key][k] = repl # just replace it
Demo:
>>> dic = {'k1':{'kk1':'vv1', 'kk2': 'vv2'}, 'k2':{'kkk1':'vvv1', 'kkk2':'vvv2'}}
>>> patch_dic(dic, 'k2', {'vvv1':'actualv1', 'vvv2':'actualv2'})
>>> print(dic)
{'k1': {'kk1': 'vv1', 'kk2': 'vv2'}, 'k2': {'kkk1': 'actualv1', 'kkk2': 'actualv2'}}

If dict2 value = dict1 key, replace entire dict2 value with dict1 value

I have two dictionaries. In both dictionaries, the value of each key is a single list. If any element in any list in dictionary 2 is equal to a key of dictionary 1, I want to replace that element with the first element in that dictionary 1 list.
In other words, I have:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb']}
and I want:
dict2 = {1:['newA', 'newB']}
I tried:
for ID1, news in dict1.items():
for x, ID2s in dict2.items():
for ID in ID2s:
if ID == ID1:
print ID1, 'match'
ID.replace(ID, news[0])
for k, v in dict2.items():
print k, v
and I got:
IDb match
IDa match
1 ['IDa', IDb']
So it looks like everything up to the replace method is working. Is there a way to make this work? To replace an entire string in a value-list with a string in another value-list?
Thanks a lot for your help.
Try this:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb']}
for key in dict2.keys():
dict2[key] = [dict1[x][0] if x in dict1.keys() else x for x in dict2[key]]
print dict2
this will print:
{1: ['newA', 'newB']}
as required.
Explanation
dict.keys() gives us just the keys of a dictionary (i.e. just the left hand side of the colon). When we use for key in dict2.keys(), at present our only key is 1. If the dictionary was larger, it'd loop through all keys.
The following line uses a list comprehension - we know that dict2[key] gives us a list (the right side of the colon), so we loop through every element of the list (for x in dict2[key]) and return the first entry of the corresponding list in dict1 only if we can find the element in the keys of dict1 (dict1[x][0] if x in dict1.keys) and otherwise leave the element untouched ([else x]).
For example, if we changed our dictionaries to be the following:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb'], 2:{'IDb', 'IDc'}}
we'd get the output:
{1: ['newA', 'newB'], 2: ['newB', 'IDc']}
because 'IDc' doesn't exist in the keys of dict1.
You could also use dictionary comprehensions, but I am not sure that they are working in Python 2.7, it may be limited to Python 3 :
# Python 3
dict2 = {k: [dict1.get(e, [e])[0] for e in v] for k,v in dict2.items()}
edit: I just checked, this is working in Python 2.7. However, dict2.items() should be replaced by dict2.iteritems() :
# Python 2.7
dict2 = {k: [dict1.get(e, [e])[0] for e in v] for k,v in dict2.iteritems()}
This was a fun one!
dict2[1] = [dict1[val][0] if val in dict1 else val for val in dict2[1]]
Or, here is the same logic without list comprehension:
new_dict = {1: []}
for val in dict2[1]:
if val in dict1:
new_dict[1].append(dict1[val][0])
else:
new_dict[1].append(val)
dict2 = new_dict

Swap keys for values in dictionary with multiple duplicate values in Python 3

I know how to swap keys and values in a dictionary, but I don't know what I should do if I want to make a set as a value for those multiple keys that correspond with that value.
I have the following code:
def bind(dict1):
dict2 = {}
for k, v in dict1.items():
dict2[v] = {k}
return dict2
The problem is, if I enter for instance
bind({'Europa': 'Jupiter', 'Psamathe': 'Neptune', 'Cordelia': 'Uranus', 'Cupid': 'Uranus'})
It would return the following:
{'Jupiter': {'Europa'}, 'Neptune': {'Psamathe'}, 'Uranus': {'Cupid'}}
while I need to have:
{'Jupiter': {'Europa'}, 'Neptune': {'Psamathe'}, 'Uranus': {'Cupid', 'Cordelia'}}
I have tried to make empty sets as values for my new dictionary by entering:
def bind(dict1):
dict2 = {}
for k, v in dict1.items():
dict2[v] = {}
return dict2
But how can I add values to the corresponding sets belonging to the key dict2[v]?
You could use a defaultdict.
from collections import defaultdict
swapped = defaultdict(set)
for k, v in source.iteritems():
swapped[v].add(k)
defaultdict transparently creates a value at any as-yet-unaccessed key using the callable provided as the initialization argument as a factory. The above is basically equivalent to:
swapped = {}
for k, v in source.iteritems():
if v not in swapped:
swapped[v] = set()
swapped[v].add(k)
>>> import collections
>>> out = collections.defaultdict(set)
>>> inval = {'Europa': 'Jupiter', 'Psamathe': 'Neptune', 'Cordelia': 'Uranus', 'Cupid': 'Uranus'}
>>> for k, v in inval.items():
... out[v].add(k)
...
>>> out
defaultdict(<type 'set'>, {'Jupiter': set(['Europa']), 'Neptune': set(['Psamathe']), 'Uranus': set(['Cordelia', 'Cupid'])})
import collections
def bind(dict1):
dict2 = collections.defaultdict(set)
for k, v in dict1.items():
dict2[v].add(k)
return dict2
result = bind({'Europa': 'Jupiter', 'Psamathe': 'Neptune', 'Cordelia': 'Uranus', 'Cupid': 'Uranus'})
print(result)
yields
defaultdict(, {'Jupiter': set(['Europa']), 'Neptune':
set(['Psamathe']), 'Uranus': set(['Cordelia', 'Cupid'])})
Alternative, you could let dict2 be a dict instead of a collections.defaultdict(set), and use the setdefault method:
def bind(dict1):
dict2 = {}
for k, v in dict1.items():
dict2.setdefault(v,set()).add(k)
return dict2
References:
set.add
collection.defaultdict
dict.setdefault

update one dictionary with another by adding values rather then replacing it

I have many dictionaries like this:
dict1 = {1:[1,2,3],2:[2,3,4]}
dict2 = {2:[3,4,5],3:[4,5,6]}
I need to get
dict = {1:[1,2,3],2:[2,3,4,3,4,5],3:[4,5,6]}
# ^
# | order is unimportant
What is the best way of doing it?
Simple iteration an extending list...
for key, value in dict2.iteritems():
dict1.setdefault(key, []).extend(value)
Iterate through the keys of dict2; if the same key exists in dict1, concatenate the lists and set in dict1; otherwise just set in dict1
dict1 = {1:[1,2,3],2:[2,3,4]}
dict2 = {2:[3,4,5],3:[4,5,6]}
dicts = [dict1, dict2]
new_dict = {}
for d in dicts:
for k, v in d.iteritems():
if new_dict.has_key(k):
new_dict[k] = new_dict[k] + v
else:
new_dict[k] = v
a = {'a' : [1,2], 'b' : [3,4]}
b = {'a' : [3,4], 'b' : [1,2]}
for key in a.keys():
for elem in a[key]:
b[key].append(elem)
Oh, maybe there's some clever way to do it with reduce, but why not just write code like a normal person.
dict = {}
for each_dict in (dict1, dict2, ...): # ... is not real code
for key, value in each_dict:
if not dict.has_key(key):
dict[key] = []
dict[key] += value # list append operator
I have many dictionaries like this:
This way lets you "glue together" multiple dictionaries at a time:
dict(
(k, sum((d.get(k, []) for d in dicts), []))
for k in set(sum((d.keys() for d in dicts), []))
)

Categories

Resources