Normally I would use sum(dict['A'].values()) in order to sum all the values in a dictionary with the key "A". However in this case it is not all the values of the "main" key I want to sum, but rather all the values where the "secondary/sub-key" has a specific name. Let me show a simplified example below:
dict = {'A':{'val1':3,'val2':5},'B':{'val1':2,'val2':6}}
sum1 = dict['A']['val1']+dict['B']['val1']
sum2 = dict['A']['val2']+dict['B']['val2']
The example above is fairly easy since it's only a 2*2 dimension, and thus I can fairly easily add the values directly. But this method is not practical when the dictionary gets larger. So I wonder what is the most efficient solution.
To sum values for a single subkey you could use sum() with a generator expression:
>>> d = {'A': {'val1': 3,'val2': 5}, 'B': {'val1': 2, 'val2': 6}}
>>> sum(x['val1'] for x in d.values())
5
To sum values for all subkeys you can use collections.Counter:
>>> from collections import Counter
>>> counter = sum(map(Counter, d.values()), Counter())
>>> dict(counter)
{'val2': 11, 'val1': 5}
You can iterate through the keys of your dict and retrieve the values to add them to a variable.
So you would start by declaring the sum variables where you will store the sums, and iterate through every key in your dict to add the corresponding values to the sum variables. You could also easily add more values in the future by adding val3 and sum3, val4 and sum4, etc. Here is an example:
my_dict = {'A':{'val1':3,'val2':5},'B':{'val1':2,'val2':6}}
# initiate variables to store the sums
sum1, sum2 = (0,) * 2
# iterate through the keys of your dict and increment the sum variables
for key in my_dict:
sum1 += my_dict[key]['val1']
sum2 += my_dict[key]['val2']
print(sum1)
print(sum2)
This prints:
5
11
Also, as #jpp mentioned, never name a variable after a class, so don't name your dictionnary dict e.g. you can name it my_dict
You can store sum of the every element inside the dict in a new dictionary
dict = {'A':{'val1':3,'val2':5},'B':{'val1':2,'val2':7}}
sums = {}
sum = 0
for element in dict:
for key in dict[element]:
sum += dict[element][key]
sums[element] = sum
sum = 0
print(sums['A']) # 8
print(sums['B']) # 9
Use collections.Counter:
>>> from collections import Counter
>>> d = {'A':{'val1':3,'val2':5},'B':{'val1':2,'val2':6}}
>>> sum((Counter(d[x]) for x in d), Counter())
Counter({'val2': 11, 'val1': 5})
Also note that you shouldn't name your dictionary as dict. It shadows the built-in dict function.
I suggest you this easily readable and understandable solution, which iterates over each key/value pair to update a new dictionary with the sum of values, whatever the size of input dictionaries. I also renamed the input dictionary into d instead of dict because dict is the name of the Python built-in class:
from collections import defaultdict
d = {'A':{'val1':3,'val2':5},'B':{'val1':2,'val2':6}}
sumDict = defaultdict(int)
for v1 in d.values():
for k2,v2 in v1.items():
sumDict[k2] += v2
print(dict(sumDict)) # {'val1': 5, 'val2': 11}
print(sumDict['val1']) # 5
print(sumDict['val2']) # 11
You can find the union of relevant keys. Then use a dictionary comprehension to construct a dictionary mapping these keys to their sums:
d = {'A':{'val1':3,'val2':5},'B':{'val1':2,'val2':6}}
sum_keys = set().union(*d.values())
sums = {k: sum(d[i].get(k, 0) for i in d) for k in sum_keys}
print(sums)
{'val1': 5, 'val2': 11}
Related
I have this dictionary (key,list)
index={'chair':['one','two','two','two'],'table':['two','three','three']}
and i want this
#1. number of times each value occurs in each key. ordered descending
indexCalc={'chair':{'two':3,'one':1}, 'table':{'three':2,'two':1}}
#2. value for maximum amount for each key
indexMax={'chair':3,'table':2}
#3. we divide each value in #1 by value in #2
indexCalcMax={'chair':{'two':3/3,'one':1/3}, 'table':{'three':2/2,'two':1/2}}
I think I should use lambda expressions, but can't come up with any idea how i can do that. Any help?
First, define your values as lists correctly:
index = {'chair': ['one','two','two','two'], 'table': ['two','three','three']}
Then use collections.Counter with dictionary comprehensions:
from collections import Counter
number of times each value occurs in each key.
res1 = {k: Counter(v) for k, v in index.items()}
value for maximum amount for each key
res2 = {k: v.most_common()[0][1] for k, v in res1.items()}
we divide each value in #1 by value in #2
res3 = {k: {m: n / res2[k] for m, n in v.items()} for k, v in res1.items()}
index={'chair':{'one','two','two','two'},'table':{'two','three','three'}}
Problem: {} is creating a set. So you should consider to convert it into list.
Now coming to your solution:
from collections import Counter
index={'chair': ['one','two','two','two'],'table':['two','three','three']}
updated_index = {'chair': dict(Counter(index['chair'])), 'table': dict(Counter(index['table']))}
updated_index_2 = {'chair': Counter(index['chair']).most_common()[0][1], 'table': Counter(index['table']).most_common()[0][1]}
print(updated_index)
print(updated_index_2)
You can use python collections library, Counter to find the count without writing any lambda function.
{'chair': {'one': 1, 'two': 3}, 'table': {'two': 1, 'three': 2}}
{'chair': 3, 'table': 2}
Firstly, you have a mistake in how you created the index dict. You should have lists as the elements for each dictionary, you currently have sets. Sets are automatically deduplicated, so you will not be able to get a proper count from there.
You should correct index to be:
index={'chair':['one','two','two','two'],'table':['two','three','three']}
You can use the Counter module in Python 3, which is a subclass of the dict module, to generate what you want for each entry in indexCalc. A counter will create a dictionary with a key, and the number of times that key exists in a collection.
indexCalc = {k, Counter(v) for k, v in index}
indexCalc looks like this:
{'chair': Counter({'two': 3, 'one': 1}), 'table': Counter({'three': 2, 'two': 1})}
We can easily find the index that corresponds to the maximum value in each sub-dictionary:
indexMax = {k: max(indexCalc[k].values()) for k in indexCalc}
indexMax looks like this:
{'chair': 3, 'table': 2}
You can create indexCalcMax with the following comprehension, which is a little ugly:
indexCalcMax = {k: {val: indexCalc[k][val] / indexMax[k] for val in indexCalc[k]} for k in indexCalc}
which is a dict-comprehension translation of this loop:
for k in indexCalc:
tmp = {}
for val in indexCalc[k]:
tmp[val] = indexCalc[k][val] / float(indexMax[k])
indexCalcMax[k] = tmp
I know this is suboptimal, but I had to do it as a thought exercise:
indexCalc = {
k: {key: len([el for el in index[k] if el == key]) for key in set(index[k])}
for k in index
}
Not exactly lambda, as suggested, but comprehensions... Don't use this code in production :) This answer is only partial, you can use the analogy and come up with the other two structures that you require.
I have a dictionary contains lists of values and a list:
dict1={'first':['hi','nice'], 'second':['night','moon']}
list1= [ 'nice','moon','hi']
I want to compare the value in the dictionary with the list1 and make a counter for the keys if the value of each key appeared in the list:
the output should like this:
first 2
second 1
here is my code:
count = 0
for list_item in list1:
for dict_v in dict1.values():
if list_item.split() == dict_v:
count+= 1
print(dict.keys,count)
any help? Thanks in advance
I would make a set out of list1 for the O(1) lookup time and access to the intersection method. Then employ a dict comprehension.
>>> dict1={'first':['hi','nice'], 'second':['night','moon']}
>>> list1= [ 'nice','moon','hi']
>>>
>>> set1 = set(list1)
>>> {k:len(set1.intersection(v)) for k, v in dict1.items()}
{'first': 2, 'second': 1}
intersection accepts any iterable argument, so creating sets from the values of dict1 is not necessary.
You can use the following dict comprehension:
{k: sum(1 for i in l if i in list1) for k, l in dict1.items()}
Given your sample input, this returns:
{'first': 2, 'second': 1}
You can get the intersection of your list and the values of dict1 using sets:
for key in dict1.keys():
count = len(set(dict1[key]) & set(list1))
print("{0}: {1}".format(key,count))
While brevity can be great, I thought it would be good to also provide an example that is as close to the OPs original code as possible:
# notice conversion to set for O(1) lookup
# instead of O(n) lookup where n is the size of the list of desired items
dict1={'first':['hi','nice'], 'second':['night','moon']}
set1= set([ 'nice','moon','hi'])
for key, values in dict1.items():
counter = 0
for val in values:
if val in set1:
counter += 1
print key, counter
Using collections.Counter
from collections import Counter
c = Counter(k for k in dict1 for i in list1 if i in dict1[k])
# Counter({'first': 2, 'second': 1})
The most simplest and basic approach would be:
dict1={'first':['hi','nice'], 'second':['night','moon']}
list1= [ 'nice','moon','hi']
listkeys=list(dict1.keys())
listvalues=list(dict1.values())
for i in range(0,len(listvalues)):
ctr=0
for j in range(0,len(listvalues[i])):
for k in range(0,len(list1)):
if list1[k]==listvalues[i][j]:
ctr+=1
print(listkeys[i],ctr)
Hope it helps.
I have arrays like this:
['[camera_positive,3]', '[lens_positive,1]', '[camera_positive,2]', '[lens_positive,1]', '[lens_positive,1]', '[camera_positive,1]']
How to sum all value on index [1] with same string on index [0]?
Example:
camera_positive = 3 + 2 + 1 = 6
lens_positive = 1 + 1 + 1 = 3
You could use set in order to extract the unique keys and then use list comprehension to compute the sum for each key:
data = [['camera_positive', 3],
['lens_positive', 1],
['camera_positive', 2],
['lens_positive', 1],
['lens_positive', 1],
['camera_positive', 1]]
keys = set(key for key, value in data)
for key1 in keys:
total = sum(value for key2, value in data if key1 == key2)
print("key='{}', sum={}".format(key1, total))
this gives:
key='camera_positive', sum=6
key='lens_positive', sum=3
I'm assuming that you have a list of list, not a list of strings as shown in the question. Otherwise you'll have to do some parsing. That said, I would solve this problem by creating a dictionary, and then iterating over the values and adding them to the dictionary as you go.
The default dict allows this program to work without getting a key error, as it'll assume 0 if the key does not exist yet. You can read up on defaultdict here: https://docs.python.org/3.3/library/collections.html#collections.defaultdict
lmk if that helps!
>>> from collections import defaultdict
>>> d = defaultdict(int)
>>> d
defaultdict(<class 'int'>, {})
>>> lst=[['a',1], ['b', 2], ['a',4]]
>>> for k, v in lst:
... d[k] += v
...
>>> d
defaultdict(<class 'int'>, {'a': 5, 'b': 2})
You could group the entries by their first index using groupby with lambda x: x[0] or operator.itemgetter(0) as key.
This is maybe a bit less code than what Nick Brady showed. However you would need to sort the list first (for the same key), so it might be slower than his approach.
I have a list of data, which has 2 values:
a 12
a 11
a 5
a 12
a 11
I would like to use a dictionary, so I can end up with a list of values for each of the key. Column 1 may have a different entry, like 'b', so I can arrange data based on column 1 as key, while column 2 is the data for each key
[a:12,11,5]
How do I achieve this? From what I read, if 2 values has the same key, the last one override the previous one, so only one key is in the dictionary.
d={}
for line in results:
templist=line.split(' ')
thekey=templist[0]
thevalue=templist[1]
if thevalue in d:
d[thekey].append(thevalue)
else:
d[thekey]=[thevalue]
Am I approaching the problem using the wrong way?
Python dicts can have only one value for a key, so you cannot assign multiple values in the fashion you are trying to.
Instead, store the mutiple values in a list corresponding to the key so that the list becomes the one value corresponding to the key:
d = {}
d["a"] = []
d["a"].append(1)
d["a"].append(2)
>>> print d
{'a': [1, 2]}
You can use a defaultdict to simplify this, which will initialise the key if it doesn't exist with an empty list as below:
from collections import defaultdict
d = defaultdict(list)
d["a"].append(1)
d["a"].append(2)
>>> print d
defaultdict(<type 'list'>, {'a': [1, 2]})
If you don't want repeat values for a key, you can use a set instead of list. But do note that a set is unordered.
from collections import defaultdict
d = defaultdict(set)
d["a"].add(1)
d["a"].add(2)
d["a"].add(1)
>>> print d
defaultdict(<type 'set'>, {'a': set([1, 2])})
If you need to maintain order, either use sorted at runtime, or use a list
with an if clause to check for values
from collections import defaultdict
d = defaultdict(list)
for item in (1, 2, 1, 2, 3, 4, 1, 2):
if item not in d["a"]:
d["a"].append(item)
>>> print d
defaultdict(<type 'list'>, {'a': [1, 2, 3, 4]})
I have a list:
list = [(a,1),(b,2),(a,3)]
I want to convert it to a dict where when there is a duplicate (eg. (a,1) and (a,3)), it will be get the average so dict will just have 1 key:value pair which would be in this case a:2.
from collections import defaultdict
l = [('a',1),('b',2),('a',3)]
d = defaultdict(list)
for pair in l:
d[pair[0]].append(pair[1]) #add each number in to the list with under the correct key
for (k,v) in d.items():
d[k] = sum(d[k])/len(d[k]) #re-assign the value associated with key k as the sum of the elements in the list divided by its length
So
print(d)
>>> defaultdict(<type 'list'>, {'a': 2, 'b': 2})
Or even nicer and producing a plain dictionary in the end:
from collections import defaultdict
l = [('a',1),('b',2),('a',3)]
temp_d = defaultdict(list)
for pair in l:
temp_d[pair[0]].append(pair[1])
#CHANGES HERE
final = dict((k,sum(v)/len(v)) for k,v in temp_d.items())
print(final)
>>>
{'a': 2, 'b': 2}
Note that if you are using 2.x (as you are, you will need to adjust the following to force float division):
(k,sum(v)/float(len(v)))
OR
sum(d[k])/float(len(d[k]))