How to get result of Counter into two lists? - python

I am using Counter from collections to count the occurrence of some numbers. I am trying to put the numbers into one list and the count into another list.
The Counter(array) returns data that likes like {(30: 2, 26: 2, 18: 2)}. I would like for there to be two arrays, say A[] and B[], where A would be [30, 26, 18] and B would be [2, 2, 2].
How would I go about doing this?

You could just zip the items from the dict that Counter returns like,
>>> vals
[26, 26, 18, 18, 30, 30]
>>> import collections
>>> collections.Counter(vals)
Counter({26: 2, 18: 2, 30: 2})
>>> zip(*collections.Counter(vals).items())
[(26, 18, 30), (2, 2, 2)]
>>> a, b = zip(*collections.Counter(vals).items())
>>> a
(26, 18, 30)
>>> b
(2, 2, 2)

Counter is a subclass of dict, so you can use the normal dictionary methods
from collections import Counter
array = [1, 2, 3, 3, 4, 4, 4]
counter = Counter(array)
items = list(counter.keys())
counts = list(counter.values())
isinstance(counter, dict) # True

Use .items() to collect the keys and values:
from collections import Counter
d=['a', 'b', 'b', 'c']
l = Counter(d)
A=[k for k, v in l.items()]
print(A)
Result: ['a', 'b', 'c']

Counter is a spcialized dict. It has keys() and values() as well as items()
from collections import Counter
c =Counter( {30: 2, 26: 2, 18: 77} )
a = list(c.keys()) # make a list from the keys view
b = list(c.values()) # make a list from the values
# or # decompose the list of key,value tuples
A, B = map(list,zip(*c.items()))
print(a,b,A,B,sep="\n")
Output:
[30, 26, 18] # a
[2, 2, 77] # b
[30, 26, 18] # A
[2, 2, 77] # B
Doku:
zip()
map

Related

How do I pick the lowest cost value for each category?

I have two lists that have the same number of elements. In the first list, an element represents a category type. In the second list, an element represents a kind of cost. Indices corresponds to each other.
For example:
category_list = [1, 2, 2, 1, 3, 3, 3, 3, 4, 2]
cost_list = [30, 45, 21, 22, 21, 32, 11, 12, 13, 11]
On the condition that I pick one for every category, I would like to minimize the cost. How can I implement this? Faster, better. Thank you for your help.
I recommended this code. In here we use the prebuilt method 'zip' in python to iteratively get the category_list and cost_list so I supposed it is good practice and then I using conditional expression to create my logic. First I want to determine in that category already in my x_dict in that expression is true I using 'min' prebuilt method to compare the value that already exists and the new value of the related key. So it is helpful to manage our logic. Otherwise, that key does not already exist then we can added key-value pair for the first time. the dictionary key is must be unique that's why we using this logic.
category_list = [1, 2, 2, 1, 3, 3, 3, 3, 4, 2]
cost_list = [30, 45, 21, 22, 21, 32, 11, 12, 13, 11]
x_dict=dict()
for cat,cost in zip(category_list,cost_list):
if cat in x_dict:
x_dict[cat]=min(x_dict[cat],cost)
else:
x_dict[cat]=cost
print(x_dict)
Output
{1: 22, 2: 11, 3: 11, 4: 13}
We can use the zip method directly and convert it to the dictionary. It can filter the unique keys but the case is it given the last value for the related key which we use like given below.
x=dict(zip(category_list,cost_list))
print(x)
output
{1: 22, 2: 11, 3: 12, 4: 13}
You can see last cost of the given list assign to the related category. Thats we give that logic for our code.
You can store the minimum cost of each category in a dict.
category_list = [1, 2, 2, 1, 3, 3, 3, 3, 4, 2]
cost_list = [30, 45, 21, 22, 21, 32, 11, 12, 13, 11]
min_cst = dict()
for cat, cst in zip(category_list, cost_list):
if cat in min_cst:
min_cst[cat] = min(min_cst[cat], cst)
else:
min_cst[cat] = cst
print(min_cst)
# {1: 22, 2: 11, 3: 11, 4: 13}
The time complexity is O(N) and space complexity is O(N).
Since there are already three nearly-identical answers using dict, here is a different answer using min only once per category:
category_list = [1, 2, 2, 1, 3, 3, 3, 3, 4, 2]
cost_list = [30, 45, 21, 22, 21, 32, 11, 12, 13, 11]
pick_indices = [min((i for i in range(len(cost_list)) if category_list[i] == cat), key=lambda i: cost_list[i]) for cat in set(category_list)]
pick_totalcost = sum(cost_list[i] for i in pick_indices)
Or alternatively:
pick_costs = [min(cost for i,(cost,cat) in enumerate(zip(cost_list, category_list)) if cat == c) for c in set(category_list)]
pick_totalcost = sum(pick_costs)
Solution 1:
You can iterate over category_list and save a min of cost_list in a dictionary that key is category_list and you can use dictionary.get() and replace min with the minimum that exist before in the dictionary.
category_list = [1, 2, 2, 1, 3, 3, 3, 3, 4, 2]
cost_list = [30, 45, 21, 22, 21, 32, 11, 12, 13, 11]
dct_min = {}
for idx in range(len(category_list)):
min_item = dct_min.get(category_list[idx], cost_list[idx])
# alternative solution by thanks #Stef
# min_item = dct_min.setdefault(category_list[idx], cost_list[idx]); if cost_list[idx] < min_item: ...
if cost_list[idx] <= min_item:
dct_min[category_list[idx]] = cost_list[idx]
print(dct_min)
Output:
{1: 22, 2: 11, 3: 11, 4: 13}
Solution 2: (you can use zip then sort tuple first base index0 then index1 and convert sorted tuple to dictionary and we know in dictionary we have only one key.)
zip_lsts = list(zip(category_list, cost_list))
dict(sorted(zip_lsts, key=lambda element: (element[0], element[1]),reverse=True))
# {4: 13, 3: 11, 2: 11, 1: 22}

create dictionary from two list with the addition of values with same key

I have two lists like below,
l1=['a', 'b', 'c', 'c', 'a','a','d','b']
l2=[2, 4, 6, 8, 10, 12, 14, 16]
Now want to create a dictionary from above list such as- key would be unique from l1 and the values from l2 will be added,
so final dictionary would look like,
d={'a':24, 'b':20, 'c': 14, 'd':14}
I could do this using a for loop but execution time will be more, looking for some python shortcuts to do this most efficiently.
You can use collections.defaultdict for this with zip to iterate parallely:
from collections import defaultdict
l1 = ['a', 'b', 'c', 'c', 'a','a','d','b']
l2 = [2, 4, 6, 8, 10, 12, 14, 16]
d = defaultdict(int)
for k, v in zip(l1, l2):
d[k] += v
print(d)
# {'a': 24, 'b': 20, 'c': 14, 'd': 14}
With a dict of comprehension:
from more_itertools import unique_everseen
d = {i: sum([l2[x] for x in [y for y,val in enumerate(l1) if val==i]]) for i in list(unique_everseen(l1))}
Output:
{'a':24, 'b':20, 'c': 14, 'd':14}
l1 = ['a', 'b', 'c', 'c', 'a','a','d','b']
l2 = [2, 4, 6, 8, 10, 12, 14, 16]
idx = 0
d = {}
for v in l1:
d[v] = d.get(v, 0) + l2[idx]
idx += 1
print d
# {'a': 24, 'b': 20, 'c': 14, 'd': 14}
You have to use the zip() function. In it we iterate in the 2 lists, then we are creating a new dictionary key j which comes from the l1 and assigning a value to it i which comes from the l2. If the key from the l1 is in the dictionary key already, it value will be added as you wanted to.
l1=['a', 'b', 'c', 'c', 'a','a','d','b']
l2=[2, 4, 6, 8, 10, 12, 14, 16]
output = {}
for j, i in zip(l1, l2):
if j in output.keys():
output[j] = output[j] + i
else:
output[j] = i
print(output)

How to get the values in the dictionary into the list form and then square them into list

I have a dictionary of values in tuple form, how to get the values in list form.
I want to get values from the tuples and create new lists and create another 3 lists with squares from them.
dictionary={1:(1,2,3),2:(3,4,5),3:(6,7,8),4:(9,10,11),5:(12,13,14)}
s=list(d.values())
d=[item for t in s for item in t]
print(d)
I used list comprehension i got this output:
[1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Using list comprehension
Expected_output:
[1,3,6,9,12],
[2,4,7,10,13],
[3,5,8,11,14],
squares**2 output above three list :
[1,9,36,81,144],
[4,16,49,100,169],
[9,25,64,121,196]
Provided with a Dictionary
First take a empty list and assign it to a variable “l”
Using list comprehension separate the values and store that in a variable
Iterate the values and append the empty list “l”
Now iterate the “l” using index values i[o], i[1], i[2] and store in various variables respectively
Using map function square the variables and store the values and print them using the list of variables
x = {
1:(1,2,3),
2:(4,5,6),
3:(7,8,9),
4:(10,11,12),
5:(13,14,15)
}
l = []
y = [i for i in x.values()]
for i in y:
l.append(i)
print(l)
m = [i[0] for i in l]
n = [i[1] for i in l]
o = [i[2] for i in l]
m1 = map(lambda i:i**2, m)
n1 = map(lambda i:i**2, n)
o1 = map(lambda i:i**2, o)
print(m)
print(list(m1))
print(n)
print(list(n1))
print(o)
print(list(o1))
you can use zip to collect the index elements of each list together, then use list comprehension to square them
dictionary={1:(1,2,3),2:(3,4,5),3:(6,7,8),4:(9,10,11),5:(12,13,14)}
list_vals = list(zip(*dictionary.values()))
squares = [[num ** 2 for num in nums] for nums in list_vals]
print(list_vals)
print(squares)
OUTPUT
[(1, 3, 6, 9, 12), (2, 4, 7, 10, 13), (3, 5, 8, 11, 14)]
[[1, 9, 36, 81, 144], [4, 16, 49, 100, 169], [9, 25, 64, 121, 196]]
Thanks to comments from #roganjosh highlighting that the dict will only be assured to be ordered if the pythong version is 3.6 or higher. If your python version is less than that you would first need to sort the values by order of the keys. Below is an example.
dictionary={2:(3,4,5),3:(6,7,8),4:(9,10,11),5:(12,13,14),1:(1,2,3)}
ordered_key_val = sorted(dictionary.items(), key=lambda items: items[0])
list_vals = list(zip(*[val for key, val in ordered_key_val]))
squares = [[num ** 2 for num in nums] for nums in list_vals]
print(list_vals)
print(squares)
You can use numpy to transpose the entire list once the values of the dictionary are obtained. You can use the below program
import numpy as np
dictionary={1:(1,2,3),2:(3,4,5),3:(6,7,8),4:(9,10,11),5:(12,13,14)}
list_out= []
for i in dictionary.keys():
list_out.append(dictionary[i])
tran_list = np.transpose(list_out)
out_list = tran_list*tran_list
Output of this is:
>>> out_list
array([[ 1, 9, 36, 81, 144],
[ 4, 16, 49, 100, 169],
[ 9, 25, 64, 121, 196]])
This is an array output! Anyway if you want it only in the list, ofcourse , you can play with it!
You can do this way:
>>> temp = list(zip(*dictionary.values()))
>>> [list(i) for i in temp]
[[1, 3, 6, 9, 12], [2, 4, 7, 10, 13], [3, 5, 8, 11, 14]]
>>> [[i**2 for i in elem] for elem in temp]
[[1, 9, 36, 81, 144], [4, 16, 49, 100, 169], [9, 25, 64, 121, 196]]
I have one dictionary here
d={1:(1,2,3),2:(4,5,6),3:(7,8,9),4:(10,11,12),5:(13,14,15)}
first I want to get values in tuple in three lists then I used list comprehension here The below code gives the tuple values in three lists
myList1 = [d [i][0] for i in (d.keys()) ]
print(myList1)
myList2 = [d [i][1] for i in (d.keys()) ]
print(myList2)
myList3 = [d [i][2] for i in (d.keys()) ]
print(myList3)
Here all the tuple values converted into list form
[1, 4, 7, 10, 13]
[2, 5, 8, 11, 14]
[3, 6, 9, 12, 15]
Now I want to squares the elements in three lists here I Used lambda expression the below code squares the elements in the lists
a1= list(map(lambda x: x**2 ,myList1))
print(a1)
a2= list(map(lambda x: x**2 ,myList2))
print(a2)
a3= list(map(lambda x: x**2 ,myList3))
print(a3)
The output is:
[1, 16, 49, 100, 169]
[4, 25, 64, 121, 196]
[9, 36, 81, 144, 225]

Python: Python:Sort values in dictionary?

I have
x = {2:[40,30],3:[24,16],4:[30,2],5:[0,80],6:[19,8]}
and I need to sort dictionary based on the 1st item in the value
so my result should be
{2:[40,30],4:[30,2],3:[24,16],6:[19,8],5:[0,80]}
All you need to do is using dict
d = dict(x)
Since your list is already in the right format to be easily converted to Dictionary, that is, you already have a key-value tuple pair as your list elements.
Simply pass it into dict():
>>> dict([(2, [40, 30]), (4, [30, 2])])
{2: [40, 30], 4: [30, 2]}
Dictionaries don't care what order their values are in:
>>> {'one': 1, 'two': 2} == {'two': 2, 'one': 1}
True
If you want to maintain order, you can use collections.OrderedDict:
>>> from collections import OrderedDict
>>> OrderedDict([(2, [40, 30]), (4, [30, 2])])
OrderedDict([(2, [40, 30]), (4, [30, 2])])
You weren't explicit in your question, but from your comments on other answers you want to preserve the order of the list in dictionary form. A standard dictionary is inherently unordered, however, you can use an OrderedDict instead:
from collections import OrderedDict
x = [(4, [30, 2]), (2, [40, 30])]
d = dict(x)
print(d)
# {2: [40, 30], 4: [30, 2]}
d = OrderedDict(x)
print(d)
# OrderedDict([(4, [30, 2]), (2, [40, 30])])
This preserves the keys in order of addition to the dictionary.

Sum different lists from dictionaries PYTHON

I have a data structure. A list of 4 dictionaries each with 4 keys and 3 values in a list.
dict_list = [0] {key1: [1, 2, 3]
key2: [4, 5, 6]
key3: [7, 8, 9]
key4: [10, 11, 12]
[1] {key1: [13.......]
key2: [16... etc.
I want to sum each sub column [1, 4, 7, 10]....[2,5,8,11] etc. into the form
new_dict_list = [0] {new_key: [(1+4+7+10), (2,5,8,11), (3,6,9,12)]
[1] {new_key2: [(13+16....) etc.
So I'm basically cascading each column within each dictionary.
I have a VERY explicit and long way to do it so far (checking the math is correct), is there any way to use list comprehensions for something this long-winded or is it not worth the effort in the end?
Use zip to group [1, 4, 7, 10]....[2,5,8,11]:
>>> d = dict_list[0]
>>> zip(*d.values())
[(7, 4, 1, 10), (8, 5, 2, 11), (9, 6, 3, 12)]
Use map to generate the new list:
>>> map(sum, zip(*d.values()))
[22, 26, 30]
If you are using python3.x, you need list(map...) to get the list.
You can use zip and sum function :
dict_lis=[{next(d.iterkeys()):map(sum,zip(*d.values()))} for d in dict_lis]
dict.iterkeys() will returns an iterator of dictionary keys which you can get the first key using next function.but note that it wouldn't return the first key in the order that you have defined your dictionaries.since dictionary items are not ordered you can use collections.OrderedDict to get a ordered dictionary.
Note that you shouldn't have same key in your dictionaries!since you can not use same key in the last combined dictionary!
example :
dict_lis=[{'key1': [1, 2, 3],'key2': [4, 5, 6],'key3': [7, 8, 9],'key4': [10, 11, 12]},{'key5': [13,14,15],'key6': [16,17,18]}]
print [{next(d.iterkeys()):map(sum,zip(*d.values()))} for d in dict_lis]
[{'key3': [22, 26, 30]}, {'key6': [29, 31, 33]}]
Original version using list comprehensions:
# set up the initial data
dict_list = []
dict_list.append({'key1': range(1,4),
'key2': range(4,7),
'key3': range(7,10),
'key4': range(10,13)})
dict_list.append({'key1': range(13,16),
'key2': range(16,19),
'key3': range(19,22),
'key4': range(22,25)})
# generate the new list
new_dict_list = []
for d in dict_list:
new_dict_list.append({'new_key': [sum(v[0] for v in d.values()),
sum(v[1] for v in d.values()),
sum(v[2] for v in d.values())] })
print new_dict_list
The output looks like this:
[{'new_key': [22, 26, 30]}, {'new_key': [70, 74, 78]}]

Categories