Related
I have a list as follows:
[[a,a,b,a,b,b,b],[5,5,4,5],[5,1,5],[2,5],[4,5],[5],[3],[5]]
The number of lists containing numerical values is the same as the elements in the first list (that contains letters "a" or "b"). The length of the lists containing numbers is unknown a priori.
Each letter corresponds to a list in this way:
a --> 5,5,4,5
a --> 5,1,5
b --> 2,5
a --> 4,5
b --> 5
b --> 3
b --> 5
And then, count each value by letters "a" or "b", while keeping the values, for example "a" has in total 6 "5", 2 "4", and 1 "1". "b" has in total 3 "5", 1 "2", and 1 "3".
Expected result:
"a" has in total 6 "5", 2 "4", and 1 "1".
"b" has in total 3 "5", 1 "2", and 1 "3".
One approach:
from collections import Counter, defaultdict
lst = [["a", "a", "b", "a", "b", "b", "b"], [5, 5, 4, 5], [5, 1, 5], [2, 5], [4, 5], [5], [3], [5]]
result = defaultdict(Counter)
head, *tail = lst
for key, values in zip(head, tail):
result[key] += Counter(values)
for key, counts in result.items():
print(key, counts)
Output
a Counter({5: 6, 4: 2, 1: 1})
b Counter({5: 3, 2: 1, 3: 1})
An alternative:
head, *tail = lst
counts = Counter((key, value) for key, values in zip(head, tail) for value in values)
result = defaultdict(dict)
for (key, value), count in counts.items():
result[key][value] = count
for key, value in result.items():
print(key, value)
Output
a {5: 6, 4: 2, 1: 1}
b {2: 1, 5: 3, 3: 1}
This would be my approach:
inputs = [['a','a','b','a','b','b','b'],[5,5,4,5],[5,1,5],[2,5],[4,5],[5],[3],[5]]
counts = {}
for k, v in zip(inputs[0], inputs[1:]):
if k in counts.keys():
counts[k] += v
else:
counts[k] = v
My output for this:
{'a': [5, 5, 4, 5, 5, 1, 5, 4, 5], 'b': [2, 5, 5, 3, 5]}
Then you can use Counters, len(), etc. to get the exact output formatting you want.
See below ( Counter and defaultdict are the main "players")
from collections import Counter,defaultdict
results = defaultdict(Counter)
data = [['a','a','b','a','b','b','b'],[5,5,4,5],[5,1,5],[2,5],[4,5],[5],[3],[5]]
for idx,x in enumerate(data[0],1):
results[x].update(data[idx])
for letter,counter in results.items():
print(f'{letter} -> {counter}')
output
a -> Counter({5: 6, 4: 2, 1: 1})
b -> Counter({5: 3, 2: 1, 3: 1})
It's a fun problem to solve.
from collections import Counter
data = [['a','a','b','a','b','b','b'],[5,5,4,5],[5,1,5],[2,5],[4,5],[5],[3],[5]]
counts = { k:Counter() for k in list(set(data[0])) }
for i, k in enumerate(data[0], 1):
counts[k].update(data[i])
print(counts)
# {'a': Counter({5: 6, 4: 2, 1: 1}), 'b': Counter({5: 3, 2: 1, 3: 1})}
l = [["a","a","b","a","b","b","b"],[5,5,4,5],[5,1,5],[2,5],[4,5],[5],[3],[5]]
d = {}
for i in l[0]:
if i not in d.keys():
d[i] = []
for i, item in zip(l[0],l[1:]):
d[i].append(item)
count_dict = {}
for i in d.keys():
count_dict[i] = {}
for j in d[i]:
elements = set(j)
for k in elements:
if str(k) not in count_dict[i].keys():
count_dict[i][str(k)] = j.count(k)
else:
count_dict[i][str(k)] += j.count(k)
for i,j in count_dict.items():
print('{} has {}'.format(i,j))
First off, you should really be doing your own homework
... I just love a good algo problem (adventOfCode, anyone?)
Steps:
don't forget " around strings in the list
create a dictionary to store counts within "a" and "b"
iterate over lists in indices 1-n
get the a/b bucket from: l[0][sublist_index - 1]
start a count for value, if not already counted: if v not in d[bucket].keys(): d[bucket][v] = 0
increment the counter for v, in the appropriate bucket: d[bucket][v] += 1
l = [["a","a","b","a","b","b","b"],[5,5,4,5],[5,1,5],[2,5],[4,5],[5],[3],[5]]
d = {"a": {}, "b": {}}
for sublist_index in range(1, len(l)):
bucket = l[0][sublist_index - 1]
for v in l[sublist_index]:
if v not in d[bucket].keys():
d[bucket][v] = 0
d[bucket][v] += 1
print(d)
and the output:
{'a': {5: 6, 4: 2, 1: 1}, 'b': {2: 1, 5: 3, 3: 1}}
I have a list of tuples like this:
list = [(1,2),(1,3),(1,5),(0,8),(0,9),(0,1),(3,6),(3,7)]
I want to build a dictionary with sets of associate values like this:
result = {1:{2,3,5},0:{8,9,1},3:{6,7}}
I have this code:
return {x:y for (x,y) in list}
result = {1: 5, 0: 1, 3: 7}
But I have only the last value, I want all associate values in a set.
Thanks in advance
defaultdict could add value for a key without checking existence
from collections import defaultdict
mylist = [(1,2),(1,3),(1,5),(0,8),(0,9),(0,1),(3,6),(3,7)]
result = defaultdict(list)
for item in mylist:
result[item[0]].append(item[1])
SOLUTION:
This code snippet should solve your problem statement:
lst = [(1,2),(1,3),(1,5),(0,8),(0,9),(0,1),(3,6),(3,7)]
output_dict = dict()
[output_dict[t[0]].add(t[1]) if t[0] in list(output_dict.keys()) else output_dict.update({t[0]: {t[1]}}) for t in lst]
print(output_dict)
OUTPUT:
{1: {2, 3, 5}, 0: {8, 9, 1}, 3: {6, 7}}
This should help u:
lst = [(1,2),(1,3),(1,5),(0,8),(0,9),(0,1),(3,6),(3,7)]
result= {}
[result.setdefault(x, set()).add(y) for x,y in lst]
print(result)
Output:
{1: {2, 3, 5}, 0: {8, 9, 1}, 3: {6, 7}}
Incase if you want one liner:
In [10]: original_list = [(1,2),(1,3),(1,5),(0,8),(0,9),(0,1),(3,6),(3,7),(1,2)]
In [11]: {x: {r for(q, r) in original_list if q == x} for (x, y) in original_list}
Out[11]: {1: {2, 3, 5}, 0: {1, 8, 9}, 3: {6, 7}}
Here it is:
result = {}
for x, y in list:
if x not in result:
result[x] = []
result[x].append(y)
print(result)
This question already has answers here:
Using a dictionary to count the items in a list
(8 answers)
Closed 7 months ago.
Given an unordered list of values like
a = [5, 1, 2, 2, 4, 3, 1, 2, 3, 1, 1, 5, 2]
How can I get the frequency of each value that appears in the list, like so?
# `a` has 4 instances of `1`, 4 of `2`, 2 of `3`, 1 of `4,` 2 of `5`
b = [4, 4, 2, 1, 2] # expected output
In Python 2.7 (or newer), you can use collections.Counter:
>>> import collections
>>> a = [5, 1, 2, 2, 4, 3, 1, 2, 3, 1, 1, 5, 2]
>>> counter = collections.Counter(a)
>>> counter
Counter({1: 4, 2: 4, 5: 2, 3: 2, 4: 1})
>>> counter.values()
dict_values([2, 4, 4, 1, 2])
>>> counter.keys()
dict_keys([5, 1, 2, 4, 3])
>>> counter.most_common(3)
[(1, 4), (2, 4), (5, 2)]
>>> dict(counter)
{5: 2, 1: 4, 2: 4, 4: 1, 3: 2}
>>> # Get the counts in order matching the original specification,
>>> # by iterating over keys in sorted order
>>> [counter[x] for x in sorted(counter.keys())]
[4, 4, 2, 1, 2]
If you are using Python 2.6 or older, you can download an implementation here.
If the list is sorted, you can use groupby from the itertools standard library (if it isn't, you can just sort it first, although this takes O(n lg n) time):
from itertools import groupby
a = [5, 1, 2, 2, 4, 3, 1, 2, 3, 1, 1, 5, 2]
[len(list(group)) for key, group in groupby(sorted(a))]
Output:
[4, 4, 2, 1, 2]
Python 2.7+ introduces Dictionary Comprehension. Building the dictionary from the list will get you the count as well as get rid of duplicates.
>>> a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> d = {x:a.count(x) for x in a}
>>> d
{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}
>>> a, b = d.keys(), d.values()
>>> a
[1, 2, 3, 4, 5]
>>> b
[4, 4, 2, 1, 2]
Count the number of appearances manually by iterating through the list and counting them up, using a collections.defaultdict to track what has been seen so far:
from collections import defaultdict
appearances = defaultdict(int)
for curr in a:
appearances[curr] += 1
In Python 2.7+, you could use collections.Counter to count items
>>> a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>>
>>> from collections import Counter
>>> c=Counter(a)
>>>
>>> c.values()
[4, 4, 2, 1, 2]
>>>
>>> c.keys()
[1, 2, 3, 4, 5]
Counting the frequency of elements is probably best done with a dictionary:
b = {}
for item in a:
b[item] = b.get(item, 0) + 1
To remove the duplicates, use a set:
a = list(set(a))
You can do this:
import numpy as np
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
np.unique(a, return_counts=True)
Output:
(array([1, 2, 3, 4, 5]), array([4, 4, 2, 1, 2], dtype=int64))
The first array is values, and the second array is the number of elements with these values.
So If you want to get just array with the numbers you should use this:
np.unique(a, return_counts=True)[1]
Here's another succint alternative using itertools.groupby which also works for unordered input:
from itertools import groupby
items = [5, 1, 1, 2, 2, 1, 1, 2, 2, 3, 4, 3, 5]
results = {value: len(list(freq)) for value, freq in groupby(sorted(items))}
results
format: {value: num_of_occurencies}
{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}
I would simply use scipy.stats.itemfreq in the following manner:
from scipy.stats import itemfreq
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
freq = itemfreq(a)
a = freq[:,0]
b = freq[:,1]
you may check the documentation here: http://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.stats.itemfreq.html
from collections import Counter
a=["E","D","C","G","B","A","B","F","D","D","C","A","G","A","C","B","F","C","B"]
counter=Counter(a)
kk=[list(counter.keys()),list(counter.values())]
pd.DataFrame(np.array(kk).T, columns=['Letter','Count'])
seta = set(a)
b = [a.count(el) for el in seta]
a = list(seta) #Only if you really want it.
Suppose we have a list:
fruits = ['banana', 'banana', 'apple', 'banana']
We can find out how many of each fruit we have in the list like so:
import numpy as np
(unique, counts) = np.unique(fruits, return_counts=True)
{x:y for x,y in zip(unique, counts)}
Result:
{'banana': 3, 'apple': 1}
This answer is more explicit
a = [1,1,1,1,2,2,2,2,3,3,3,4,4]
d = {}
for item in a:
if item in d:
d[item] = d.get(item)+1
else:
d[item] = 1
for k,v in d.items():
print(str(k)+':'+str(v))
# output
#1:4
#2:4
#3:3
#4:2
#remove dups
d = set(a)
print(d)
#{1, 2, 3, 4}
For your first question, iterate the list and use a dictionary to keep track of an elements existsence.
For your second question, just use the set operator.
def frequencyDistribution(data):
return {i: data.count(i) for i in data}
print frequencyDistribution([1,2,3,4])
...
{1: 1, 2: 1, 3: 1, 4: 1} # originalNumber: count
I am quite late, but this will also work, and will help others:
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
freq_list = []
a_l = list(set(a))
for x in a_l:
freq_list.append(a.count(x))
print 'Freq',freq_list
print 'number',a_l
will produce this..
Freq [4, 4, 2, 1, 2]
number[1, 2, 3, 4, 5]
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
counts = dict.fromkeys(a, 0)
for el in a: counts[el] += 1
print(counts)
# {1: 4, 2: 4, 3: 2, 4: 1, 5: 2}
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
# 1. Get counts and store in another list
output = []
for i in set(a):
output.append(a.count(i))
print(output)
# 2. Remove duplicates using set constructor
a = list(set(a))
print(a)
Set collection does not allow duplicates, passing a list to the set() constructor will give an iterable of totally unique objects. count() function returns an integer count when an object that is in a list is passed. With that the unique objects are counted and each count value is stored by appending to an empty list output
list() constructor is used to convert the set(a) into list and referred by the same variable a
Output
D:\MLrec\venv\Scripts\python.exe D:/MLrec/listgroup.py
[4, 4, 2, 1, 2]
[1, 2, 3, 4, 5]
Simple solution using a dictionary.
def frequency(l):
d = {}
for i in l:
if i in d.keys():
d[i] += 1
else:
d[i] = 1
for k, v in d.iteritems():
if v ==max (d.values()):
return k,d.keys()
print(frequency([10,10,10,10,20,20,20,20,40,40,50,50,30]))
#!usr/bin/python
def frq(words):
freq = {}
for w in words:
if w in freq:
freq[w] = freq.get(w)+1
else:
freq[w] =1
return freq
fp = open("poem","r")
list = fp.read()
fp.close()
input = list.split()
print input
d = frq(input)
print "frequency of input\n: "
print d
fp1 = open("output.txt","w+")
for k,v in d.items():
fp1.write(str(k)+':'+str(v)+"\n")
fp1.close()
from collections import OrderedDict
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
def get_count(lists):
dictionary = OrderedDict()
for val in lists:
dictionary.setdefault(val,[]).append(1)
return [sum(val) for val in dictionary.values()]
print(get_count(a))
>>>[4, 4, 2, 1, 2]
To remove duplicates and Maintain order:
list(dict.fromkeys(get_count(a)))
>>>[4, 2, 1]
i'm using Counter to generate a freq. dict from text file words in 1 line of code
def _fileIndex(fh):
''' create a dict using Counter of a
flat list of words (re.findall(re.compile(r"[a-zA-Z]+"), lines)) in (lines in file->for lines in fh)
'''
return Counter(
[wrd.lower() for wrdList in
[words for words in
[re.findall(re.compile(r'[a-zA-Z]+'), lines) for lines in fh]]
for wrd in wrdList])
For the record, a functional answer:
>>> L = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> import functools
>>> >>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc,1)] if e<=len(acc) else acc+[0 for _ in range(e-len(acc)-1)]+[1], L, [])
[4, 4, 2, 1, 2]
It's cleaner if you count zeroes too:
>>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc)] if e<len(acc) else acc+[0 for _ in range(e-len(acc))]+[1], L, [])
[0, 4, 4, 2, 1, 2]
An explanation:
we start with an empty acc list;
if the next element e of L is lower than the size of acc, we just update this element: v+(i==e) means v+1 if the index i of acc is the current element e, otherwise the previous value v;
if the next element e of L is greater or equals to the size of acc, we have to expand acc to host the new 1.
The elements do not have to be sorted (itertools.groupby). You'll get weird results if you have negative numbers.
Another approach of doing this, albeit by using a heavier but powerful library - NLTK.
import nltk
fdist = nltk.FreqDist(a)
fdist.values()
fdist.most_common()
Found another way of doing this, using sets.
#ar is the list of elements
#convert ar to set to get unique elements
sock_set = set(ar)
#create dictionary of frequency of socks
sock_dict = {}
for sock in sock_set:
sock_dict[sock] = ar.count(sock)
For an unordered list you should use:
[a.count(el) for el in set(a)]
The output is
[4, 4, 2, 1, 2]
Yet another solution with another algorithm without using collections:
def countFreq(A):
n=len(A)
count=[0]*n # Create a new list initialized with '0'
for i in range(n):
count[A[i]]+= 1 # increase occurrence for value A[i]
return [x for x in count if x] # return non-zero count
num=[3,2,3,5,5,3,7,6,4,6,7,2]
print ('\nelements are:\t',num)
count_dict={}
for elements in num:
count_dict[elements]=num.count(elements)
print ('\nfrequency:\t',count_dict)
You can use the in-built function provided in python
l.count(l[i])
d=[]
for i in range(len(l)):
if l[i] not in d:
d.append(l[i])
print(l.count(l[i])
The above code automatically removes duplicates in a list and also prints the frequency of each element in original list and the list without duplicates.
Two birds for one shot ! X D
This approach can be tried if you don't want to use any library and keep it simple and short!
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
marked = []
b = [(a.count(i), marked.append(i))[0] for i in a if i not in marked]
print(b)
o/p
[4, 4, 2, 1, 2]
Could you explain how to assign certain scores from a list to values in multiple lists and get the total score for each value?
score = [1,2,3,4,5] assigne a score based on the position in the list
l_1 = [a,b,c,d,e]
assign a=1, b=2, c=3, d=4, e=5
l_2 = [c,a,d,e,b]
assign c=1, a=2, d=3, e=4, b=5
I am trying to get the result like
{'e':9, 'b': 7, 'd':7, 'c': 4, 'a': 3}
Thank you!
You can zip the values of score to each list, which gives you a tuple of (key, value) for each letter-score combination. Make each zipped object a dict. Then use a dict comprehension to add the values for each key together.
d_1 = dict(zip(l_1, score))
d_2 = dict(zip(l_2, score))
{k: v + d_2[k] for k, v in d_1.items()}
# {'a': 3, 'b': 7, 'c': 4, 'd': 7, 'e': 9}
You better use zip function:
dic = {'a':0, 'b': 0, 'c':0, 'd': 0, 'e': 0}
def score(dic, *args):
for lst in args:
for k, v in zip(lst, range(len(lst))):
dic[k] += v+1
return dic
l_1 = ['a','b','c','d','e']
l_2 = ['c','a','d','e','b']
score(dic, l_1, l_2)
Instead of storing your lists in separate variables, you should put them in a list of lists so that you can iterate through it and calculate the sums of the scores according to each key's indices in the sub-lists:
score = [1, 2, 3, 4, 5]
lists = [
['a','b','c','d','e'],
['c','a','d','e','b']
]
d = {}
for l in lists:
for i, k in enumerate(l):
d[k] = d.get(k, 0) + score[i]
d would become:
{'a': 3, 'b': 7, 'c': 4, 'd': 7, 'e': 9}
from collections import defaultdict
score = [1,2,3,4,5] # note: 0 no need to use this list if there is no scenario like [5,6,9,10,4]
l_1 = ['a','b','c','d','e']
l_2 = ['c','a','d','e','b']
score_dict = defaultdict(int)
'''
for note: 0
if your score is always consecutive
like score = [2,3,4,5,6] or [5,6,7,8,9]...
you don't need to have seperate list of score you can set
start = score_of_char_at_first_position_ie_at_zero-th_index
like start = 2, or start = 5
else use this function
def add2ScoreDict( lst):
for pos_score, char in zip(score,lst):
score_dict[char] += pos_score
'''
def add2ScoreDict( lst):
for pos, char in enumerate( lst,start =1):
score_dict[char] += pos
# note: 1
add2ScoreDict( l_1)
add2ScoreDict( l_2)
#print(score_dict) # defaultdict(<class 'int'>, {'a': 3, 'b': 7, 'c': 4, 'd': 7, 'e': 9})
score_dict = dict(sorted(score_dict.items(), reverse = True, key=lambda x: x[1]))
print(score_dict) # {'e': 9, 'b': 7, 'd': 7, 'c': 4, 'a': 3}
edit 1:
if you have multiple lists put them in list_of_list = [l_1, l_2] so that you don't have to call func add2ScoreDict yourself again and again.
# for note: 1
for lst in list_of_list:
add2ScoreDict( lst)
You could zip both lists with score as one list l3 then you could use dictionary comprehension with filterto construct your dicitonary. The key being index 1 of the the newly formed tuples in l3, and the value being the sum of all index 0's in l3 after creating a sublist that is filtered for only matching index 0's
score = [1,2,3,4,5]
l_1 = ['a', 'b', 'c', 'd', 'e']
l_2 = ['c', 'a', 'd', 'e', 'b']
l3 = [*zip(score, l_1), *zip(score,l_2)]
d = {i[1]: sum([j[0] for j in list(filter(lambda x: x[1] ==i[1], l3))]) for i in l3}
{'a': 3, 'b': 7, 'c': 4, 'd': 7, 'e': 9}
Expanded Explanation:
d = {}
for i in l3:
f = list(filter(lambda x: x[1] == i[1], l3))
vals = []
for j in f:
vals.append(j[0])
total_vals = sum(vals)
d[i[1]] = total_vals
The simplest way is probably to use a Counter from the Python standard library.
from collections import Counter
tally = Counter()
scores = [1, 2, 3, 4, 5]
def add_scores(letters):
for letter, score in zip(letters, scores):
tally[letter] += score
L1 = ['a', 'b', 'c', 'd', 'e']
add_scores(L1)
L2 = ['c', 'a', 'd', 'e', 'b']
add_scores(L2)
print(tally)
>>> python tally.py
Counter({'e': 9, 'b': 7, 'd': 7, 'c': 4, 'a': 3})
zip is used to pair letters and scores, a for loop to iterate over them and a Counter to collect the results. A Counter is actually a dictionary, so you can write things like
tally['a']
to get the score for letter a or
for letter, score in tally.items():
print('Letter %s scored %s' % (letter, score))
to print the results, just as you would with a normal dictionary.
Finally, small ells and letter O's can be troublesome as variable names because they are hard to distinguish from ones and zeros. The Python style guide (often referred to as PEP8) recommends avoiding them.
This question already has answers here:
Assign a number to each unique value in a list
(9 answers)
Closed 5 years ago.
I have a list, let say
L = ['apple','bat','apple','car','pet','bat'].
I want to convert it into
Lnew = [ 1,2,1,3,4,2].
Every unique string is associated with a number.
I have a java solution using hashmap, but I don't know how to use hashmap in python.
Please help.
Here's a quick solution:
l = ['apple','bat','apple','car','pet','bat']
Create a dict that maps all unique strings to integers:
d = dict([(y,x+1) for x,y in enumerate(sorted(set(l)))])
Map each string in the original list to its respective integer:
print [d[x] for x in l]
# [1, 2, 1, 3, 4, 2]
x = list(set(L))
dic = dict(zip(x, list(range(1,len(x)+1))))
>>> [dic[v] for v in L]
[1, 2, 1, 3, 4, 2]
You can use a map dictionary:
d = {'apple':1, 'bat':2, 'car':3, 'pet':4}
L = ['apple','bat','apple','car','pet','bat']
[d[x] for x in L] # [1, 2, 1, 3, 4, 2]
For auto creating map dictionary you can use defaultdict(int) with a counter.
from collections import defaultdict
d = defaultdict(int)
co = 1
for x in L:
if not d[x]:
d[x] = co
co+=1
d # defaultdict(<class 'int'>, {'pet': 4, 'bat': 2, 'apple': 1, 'car': 3})
Or as #Stuart mentioned you can use d = dict(zip(set(L), range(len(L)))) for creating dictionary
You'd use a hashmap in Python, too, but we call it a dict.
>>> L = ['apple','bat','apple','car','pet','bat']
>>> idx = 1
>>> seen_first = {}
>>>
>>> for word in L:
... if word not in seen_first:
... seen_first[word] = idx
... idx += 1
...
>>> [seen_first[word] for word in L]
[1, 2, 1, 3, 4, 2]
You can try:
>>> L = ['apple','bat','apple','car','pet','bat']
>>> l_dict = dict(zip(set(L), range(len(L))))
>>> print l_dict
{'pet': 0, 'car': 1, 'bat': 2, 'apple': 3}
>>> [l_dict[x] for x in L]
[3, 2, 3, 1, 0, 2]
Lnew = []
for s in L:
Lnew.append(hash(s)) # hash(x) returns a unique int based on string