Python: sum values of dict which keys are values in another dict - python

Say that we have two dictionaries:
d1={'A':['a','b','c'],'B':['d','e']}
d2={'a':3,'b':1,'c':1,'d':2,'e':0}
And that we need to compute a third dictionary that has the same keys as d1, and for values the sum of the values in d2 that correspond to those keys that are, in turn, values ind1.
Example:
d3={'A':5,'B':2}
where 5 is assigned to A because it is the sum of the values of a,b,c, which are assigned to A in d1.
My attempt:
d3={key:sum(d2[i] for i in d1[j] for j in d1.keys()) for key in d1.keys()}
returns:
NameError: global name 'j' is not defined
Sorry for the trivial question, but what am I missing here?

It's simpler than that if you use dict.items():
d3 = {key: sum(d2[v] for v in val) for key, val in d1.items()}

d3 = {}
for k,v in d1.items():
d3[k] = sum([ d2[x] for x in v ])

d1={'A':['a','b','c'],'B':['d','e']}
d2={'a':3,'b':1,'c':1,'d':2,'e':0}
dict(zip(d1.keys(), map(lambda x:sum(d2.get(i) for i in x[1]), d1.items())))

Related

Merging two columns of a dataframe which contains dictionaries and storing it into other column in a data frame

I have a data frame df which has two columns a and b which contains dictionaries and I want to merge these two dictionaries and store the merged dictionaries in a new columns c. One sample data point is :
df :
a b c
------------------------------------------------------------
{x:{y:{z:u}} {w:{f:{h:l}} {x:{y:{z:u}},{w:{f:{h:l}}
I have a and b and I want c.
I have a function that merges the two dictionaries but I am not able to assign the merge dictionaries to column c.
The function that I have for merging two dictionaries:
# Function for merging two dictionaries and adding values if keys are same
def merge_and_add(dict1, dict2):
# We loop over the key and value pairs of the second dictionary...
for k, v in dict2.items():
# If the key is also found in the keys of the first dictionary, and...
if k in dict1.keys():
# If the value is a dictionary...
if isinstance(v, dict):
# we pass this value to the merge_and_add function, together with the value of first dictionary with
# the same key and we overwrite this value with the output.
dict1[k] = merge_and_add(dict1[k], v)
# If the value is an integer...
elif isinstance(v, int):
# we add the value of the key value pair of the second dictionary to the value of the first
# dictionary with the same key.
dict1[k] = dict1[k] + v
# If the key is not found, the key and value of the second should be appended to the first dictionary
else:
dict1[k] = v
# return the first dictionary
return dict1
I am trying the following but it isn't working:
df_curr_hist['latest'] = np.nan
def latest(df):
idx = 0
while idx < len(df):
curr_dict = df.iloc[idx]['current']
hist_dict = df.iloc[idx]['history']
df.latest[idx] = merge_and_add(curr_dict, hist_dict)
return df
Firstly, you should know that dictionaries are not passed as values in function arguments. Therefore, in your current code, modifications are made to original dictionaries when creating the new combined dictionary. You can handle that by using copies of the dictionaries to work with.
x = {'a':{'b':2}}
y = {'c':{'e':4}}
e = pd.DataFrame({'a':[x], 'b': [y]})
def merge_and_add(x, y):
dict1 = x.copy()
dict2 = y.copy()
# We loop over the key and value pairs of the second dictionary...
for k, v in dict2.items():
# If the key is also found in the keys of the first dictionary, and...
if k in dict1.keys():
# If the value is a dictionary...
if isinstance(v, dict):
# we pass this value to the merge_and_add function, together with the value of first dictionary with
# the same key and we overwrite this value with the output.
dict1[k] = merge_and_add(dict1[k], v)
# If the value is an integer...
elif isinstance(v, int):
# we add the value of the key value pair of the second dictionary to the value of the first
# dictionary with the same key.
dict1[k] = dict1[k] + v
# If the key is not found, the key and value of the second should be appended to the first dictionary
else:
dict1[k] = v
# return the first dictionary
return dict1
e['c'] = e.apply(lambda x : merge_and_add(x.a, x.b), axis = 1)
The final output looks like
a b c
0 {'a': {'b': 2}} {'c': {'e': 4}} {'a': {'b': 2}, 'c': {'e': 4}}

Merge two dictionaries conditionally using dict comprehension

I'd like two join two dictionaries based on the value of d1 and a substring of the key of d2. The resulting dictionary has the key of d1 with the corresponding value of d2.
d1 = {'web02': '23', 'web01': '50'}
d2 = {'server/dc-50': 's01.local', 'server/dc-23': 's02.local'}
Would result in = {web01:s01.local, web02:s02.local}
I guess this is what you need :
result = {k1:v2 for k1,v1 in d1.items() for k2,v2 in d2.items() if v1 in k2}
Output :
{'web02': 's02.local', 'web01': 's01.local'}
This is done without a nested loop by getting the value using string formatting:
data = {k: d2['server/dc-' + v] for k, v in d1.items()}
Prints:
{'web02': 's02.local', 'web01': 's01.local'}

Why isnt the output showing k1, k2, k3?

I've been trying to learn Python and have come across this issue. I can't figure out how the current output came about.
d={'k1':1,'k2':2,'k3':3}
for key,value in d.keys() :
print(key)
Output:
k
k
k
I expected the output to be:
k1
k2
k3
You are trying to print all key, value pair from your dictionary d. But you are only able to see first character of the key when you try to print key. I will explain you by splitting your for loop for key,value in d.keys().
This is your dictionary, d
d = {'k1':1,'k2':2,'k3':3}
The for loop takes d.keys() and iterates. d.keys() look like this
print(d.keys()) # outputs dict_keys(['k1', 'k2', 'k3'])
for loop iterates over this list of keys ['k1', 'k2', 'k3']
But when you do, this
key,value = 'k1' # this happens with each of the keys in the list
print(key,value) # output k 1
Your key k1 got split into two single character strings k and 1 which can be termed as an unintentional tuple creation #inquisitiveOne and gets assigned to key and value variables respectively.
When you try to print value inside the for loop, you will see 1, 2, 3 but that is in fact the second character of the key attribute and not the value attribute. If you try printing, print(type(value)) you will get to know that it is in fact a string variable and not an integer.
To get the proper value of the key you need to only use a single variable.
d={'k1':1,'k2':2,'k3':3}
for key in d.keys():
print(key)
Output:
k1
k2
k3
As mentioned by #asikorski you can achieve the same using just for key in d: print(key)
If you need to get key, value pairs. Then use d.items()
for key,value in d.items():
print(key,value)
Output:
k1 1
k2 2
k3 3
Hope it helps!
d.keys() returns ['k1', 'k2', 'k3'], but you split that into two parts with key, value, so key=='k', value=='1' the first time, and key=='k', value=='2' the second time, and so on. What you want is:
for key in d.keys():
print(key)
But you can do better and iterate directly over the dictionary without using the .keys() method:
for key in d:
print(key)
Finally, if you need to use both keys and values:
for key, values in d.items():
print(key)
print(value)
d.keys() is a list and it's value will be ["k1", "k2", "k3"]
>> d.keys()
["k1", "k2", "k3"]
When you use for key,value in d.keys(), unpacking will happen on the string value. Which means from "k1", "k" will be assigned to key and "1" will be assigned to value.
Luckily it didn't give error because there were only 2 characters in the string.
>> key, value = "k1"
>> key
k
>> value
1
And, that is the reason it printed k k k in console.!
The right way is to iterate through k.items()
for key,value in d.items():
print(key,value)
Output
k1 1
k2 2
k3 3
d={'k1':1,'k2':2,'k3':3}
for key in d.keys() :
print(key)
Try this code, this should work.
for getting the keys you need the keys API:
d={'k1':1,'k2':2,'k3':3}
for key in d.keys() :
print(key)
for getting the values use the values API:
d={'k1':1,'k2':2,'k3':3}
for value in d.values() :
print(value)
for getting keys and values there is the items API:
d={'k1':1,'k2':2,'k3':3}
for key,value in d.items() :
print(key)
print(value)
hope it helps
Answer is unintentional tuple creation.
In the statement:
for key,value in d.keys() :
you are creating a tuple unintentionally.
>>> key, value = "k1"
>>> key
'k'
>>> value
'1'
Note that the brackets are optional for creating a tuple.
The above is the same as:
>>> (key, value) = "k1"
>>> key
'k'
>>> value
'1'
>>>
Hence the output.
The problem is in your for loop:
for key,value in d.keys() :
d.keys() is an iterable (technically a dict_keys object) that contains only the keys of d: k1, k2, and k3.
Your for loop unpacks each string into k (represented by key) and a number (represented by value). You then print only key, which in each instance is k.
To remedy the issue, simply stop unpacking the keys:
for key in d.keys():

Getting a specific value of a key in a dictionary?

I have a dictionary like this:
d = {'k1':[0.2,0.65,0.23], 'k2':[0.32,1.2,3.3], 'k3':[1.8,0.6,0.4], ...}
So, I want to get a list of the key and the second value of each key in a list. I have tried this code:
names = list(d.keys())
values = list(d.values())
The first line is correct and gives me the list of all keys, but the second line provides all the values, which is not what I needed. So I need only the second or the third value of each key. Any suggestions?
Iterate over the dict and get the v[1] for each key, in a new dict:
d = {'k1':[0.2,0.65,0.23], 'k2':[0.32,1.2,3.3], 'k3':[1.8,0.6,0.4]}
print({k:v[1] for k,v in d.items()})
OUTPUT:
{'k1': 0.65, 'k2': 1.2, 'k3': 0.6}
try:
mylist = [(k, v[1]) for k, v in d.items()]
{k:v[1] for k,v in d.items()}
Create a new dict with the second value from the list-value of the original dict using a dictionary comprehension.
This will help you:
names = list(d.keys())
values = [v[1] for v in d.values()]
This iterate key and values per key
for k,v in d.items():
print("Key: %s" %k)
print("Values: %s" %v)
print("-"*8)
>>> import numpy as np
>>> d = {'k1':[0.2,0.65,0.23], 'k2':[0.32,1.2,3.3], 'k3':[1.8,0.6,0.4]}
>>> np.array(list(d.values()))[:,1]
Output:
array([0.65, 1.2 , 0.6 ])
d = {k1:[0.2,0.65,0.23], k2:[0.32,1.2,3.3], k3:[1.8,0.6,0.4], ...}
for fetching only 2nd element from the values, Below code will print only 2nd elements of each key
example - [v[1] for k,v in d.iteritems()]
prints [0.65,1.2,0.6]
for fetching key:value
{k:v[1] for k,v in d.iteritems()}
prints {'k1':0.65,'k2':1.2,'k3':0.6}
for fetching 2nd and 3rd element both , something like this can be done
{k:[v[1],v[2]] for k,v in d.iteritems()}

Check if value of one dictionary is the key for the other

I basically want to check if the value in one dictionary is the key in the other.
So for example, I have two dictionaries
a = {armani: jeans, dolce: gabbana}
b = {jeans: robo, jobs: versace}
I wrote code to do the check such that it only obtains the values that is the key in the other dictionary. So in this case, I just want to display {armani: robo} as jeans was already in both. So like the value of jeans in the second dictionary then becomes the main value in the new final dictionary
This is the code:
{k:v for k,v in a.items() if v in b.items()}
But it doesn't work and I don't know how to do the check to see if the value is the key in another list
This should work:
{k:b[v] for k,v in a.items() if v in b}
You were just missing two elements:
You don't need to write if v in b.items() because Python interprets if v in b as "if v is in the keys of b".
You need to map k not to v itself, but to v's value in b, which is b[v].
Alternatively, you could filter with set intersection.
a = {'armani': 'jeans', 'dolce': 'gabbana'}
b = {'jeans': 'robo', 'jobs': 'versace'}
c = set(a.values()).intersection(b)
d = {k:b[k] for k in c}
# or as a one-liner
e = {k:b[k] for k in set(a.values()).intersection(b)}
It might be faster than looping through the whole dictionary.
I think you need:
a = {"armani": "jeans", "dolce": "gabbana"}
b = {"jeans": "robo", "jobs": "versace"}
res = {k1:v2 for k1,v1 in a.items() for k2,v2 in b.items() if v1 ==k2}
print(res)
Output:
{'armani': 'robo'}

Categories