I have a list of lists:
countall = [[5, 0], [4, 1], [4, 1], [3, 2], [4, 1], [3, 2], [3, 2], [2, 3], [4, 1], [3, 2], [3, 2], [2, 3], [3, 2], [2, 3], [2, 3], [1, 4], [4, 1], [3, 2], [3, 2], [2, 3], [3, 2], [2, 3], [2, 3], [1, 4], [3, 2], [2, 3], [2, 3], [1, 4], [2, 3], [1, 4], [1, 4], [0, 5]]
I would like to find the frequency of sub-lists in the above list.
I have tried to use itertools:
freq = [len(list(group)) for x in countall for key, group in groupby(x)]
However, I am getting the wrong results:
[1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1]
What is wrong with my list comprehension?
Groupby seems to deal with sequences that come after each other. To use it you would need to sort the list first. Another option is to use the Counter class:
from collections import Counter
countall = [[5, 0], [4, 1], [4, 1], [3, 2], [4, 1], [3, 2], [3, 2], [2, 3], [4, 1], [3, 2], [3, 2], [2, 3], [3, 2], [2, 3], [2, 3], [1, 4], [4, 1], [3, 2], [3, 2], [2, 3], [3, 2], [2, 3], [2, 3], [1, 4], [3, 2], [2, 3], [2, 3], [1, 4], [2, 3], [1, 4], [1, 4], [0, 5]]
Counter([tuple(x) for x in countall])
Output:
Counter({(3, 2): 10, (2, 3): 10, (1, 4): 5, (4, 1): 5, (5, 0): 1, (0, 5): 1})
as pointed by ForceBru first sort your list then use groupby:
from itertools import groupby
countall = [[5, 0], [4, 1], [4, 1], [3, 2], [4, 1], [3, 2], [3, 2], [2, 3], [4, 1], [3, 2], [3, 2], [2, 3], [3, 2], [2, 3], [2, 3], [1, 4], [4, 1], [3, 2], [3, 2], [2, 3], [3, 2], [2, 3], [2, 3], [1, 4], [3, 2], [2, 3], [2, 3], [1, 4], [2, 3], [1, 4], [1, 4], [0, 5]]
freq = [(key, len(list(x))) for key, x in groupby(sorted(countall))]
print(freq)
output:
[([0, 5], 1), ([1, 4], 5), ([2, 3], 10), ([3, 2], 10), ([4, 1], 5), ([5, 0], 1)]
your code has bugs:
freq = [len(list(group)) for x in countall for key, group in groupby(x)]
^paranthesis missing
Then you are grouping each individual list in countall which is not needed.
for x in countall for key, group in groupby(x)
yo can directly groupby on sorted(countall)
Also, as answered by #Bemmu you can use collections.Counter. But that does not support list so first you will have to convert your data to tupple or string then use Counter
As noted in comments you will need to sort if you are using groupby.
Code:
import itertools as it
freq = {tuple(key): len(list(group)) for key, group in it.groupby(sorted(countall))}
Test Code:
countall = [[5, 0], [4, 1], [4, 1], [3, 2], [4, 1], [3, 2], [3, 2], [2, 3],
[4, 1], [3, 2], [3, 2], [2, 3], [3, 2], [2, 3], [2, 3], [1, 4],
[4, 1], [3, 2], [3, 2], [2, 3], [3, 2], [2, 3], [2, 3], [1, 4],
[3, 2], [2, 3], [2, 3], [1, 4], [2, 3], [1, 4], [1, 4], [0, 5]]
print(freq)
Results:
{(3, 2): 10, (1, 4): 5, (2, 3): 10, (5, 0): 1, (0, 5): 1, (4, 1): 5}
Related
I would like to sum from list of list as below
array([[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]]]
What i want is to sum like below
[1,1,1]+[1,1,1]+[1,1,1] = 9
[2,2,2]+[2,2,2]+[2,2,2] = 18
.... = 27
= 36
= 45
And return a list like below as the final list:
[9,18,27,36,45]
You can use np.sum
a = np.array([[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]]])
res = np.sum(a, axis=(0,2))
# Does reduction along axis 0 and 2 by doing summation.
# numpy takes tuple of axis indices to do reduction
# simultaneously along those axis.
print(res.tolist())
>> [ 9, 18, 27, 36, 45]
import numpy as np
lis=np.array([[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]]])
print(lis.sum(axis=0).sum(axis=1))
easiest I think with numpy.
output
[ 9 18 27 36 45]
Using zip()
Code:
import numpy as np
lis=np.array([[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]]])
res=[]
for i in zip(*lis):
res.append(sum(sum(i)))
print(res)
Output:
[9, 18, 27, 36, 45]
List comprehension:
print([sum(sum(i)) for i in zip(*lis)]) #Same output.
a = [[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]],
[[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]]]
result = [sum(x)+sum(y)+sum(z) for x,y,z in zip(a[0], a[1], a[1])]
This is really not 'python-like' solution, but I believe it will suit you well.
import numpy as np
A = np.array([[[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4], [5, 5, 5]],
[[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4], [5, 5, 5]],
[[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4], [5, 5, 5]]])
s = [0 for i in range(len(A[0]))]
for element in A:
for i, ar in enumerate(element):
s[i] += sum(ar)
print(s)
I have list of lists of lists and need to combine the inner lists accordingly.
For example:
1. mylist=[[[1]], [[2]]]
2.
mylist= [[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
[[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]],
[[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]]]
(in short-[[[1]*3]*4, [[2]*3]*4, [[3]*3]*4])
Expected output-
[[[1, 2]]]
[[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]]
(in short-[[[1, 2, 3]]*3]*4)
This is what I have untill now-
def combine_channels(mylist):
elements = [[] for _ in range(len(mylist[0]))]
for l1 in mylist:
for idx, l2 in enumerate(l1):
elements[idx] += l2
return [elements]
The problem is that the output is (for input example 2)-
[[[1, 1, 1, 2, 2, 2, 3, 3, 3],
[1, 1, 1, 2, 2, 2, 3, 3, 3],
[1, 1, 1, 2, 2, 2, 3, 3, 3],
[1, 1, 1, 2, 2, 2, 3, 3, 3]]]
and not-
[[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]]
mylist = [[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
[[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]],
[[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]]]
def combine_channels(mylist):
def list_zip(_list):
return list(zip(*_list))
elements = []
for l in list_zip(mylist):
elements.append(list_zip(l))
return elements
combine_channels(mylist)
I have a list l = [1, 2, 3, 4, 5] and would like to generate all possible combinations assuming the elements of l are repeated N times.
Example:
[1, 2, 3, 4, 5] with N = 2 would yield
[1, 1], [1, 2], [1, 3], [1, 4], [1, 5]
[2, 1], [2, 2], [2, 3], [2, 4], [2, 5]
[3, 1], [3, 2], [3, 3], [3, 4], [3, 5]
[4, 1], [4, 2], [4, 3], [4, 4], [4, 5]
[5, 1], [5, 2], [5, 3], [5, 4], [5, 5]
Thanks!
You want itertools.product:
>>> from itertools import product
>>> list(map(list, product([1, 2, 3, 4, 5], repeat=2)))
[[1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [2, 1], [2, 2], [2, 3], [2, 4], [2, 5], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [4, 1], [4, 2], [4, 3], [4, 4], [4, 5], [5, 1], [5, 2], [5, 3], [5, 4], [5, 5]]
Say I have a list inside a list, that is contained inside a list. For example:
foo = [[[2, 2, 2], [1, 1, 1], [3, 3, 3]], [[2, 2, 2], [1, 1, 1], [3, 3, 3]]]
And I wanted to sort it in order:
foo = [[[1, 1, 1], [2, 2, 2], [3, 3, 3]], [[1, 1, 1], [2, 2, 2], [3, 3, 3]]]
I could use [sorted(i) for i in foo] to achieve this. However is there some way to sort this list without list comprehension (or creating a new list)?
The values inside the lists themselves will change but do not need to be sorted.
Everything I have tried just boils down to the same method as above.
If you want to avoid creating a new list, then just iterate over the lists and call .sort()
>>> foo = [[[2, 2, 2], [1, 1, 1], [3, 3, 3]], [[2, 2, 2], [1, 1, 1], [3, 3, 3]]]
for i in foo:
i.sort()
>>> foo
[[[1, 1, 1], [2, 2, 2], [3, 3, 3]], [[1, 1, 1], [2, 2, 2], [3, 3, 3]]]
If you don't mind creating a new list, how about using map function:
In [1]: foo = [[[2, 2, 2], [1, 1, 1], [3, 3, 3]], [[2, 2, 2], [1, 1, 1], [3, 3, 3]]]
In [2]: list(map(sorted, foo))
Out[2]: [[[1, 1, 1], [2, 2, 2], [3, 3, 3]], [[1, 1, 1], [2, 2, 2], [3, 3, 3]]]
I have a program which outputs solutions, which are lists of numbers as such:
[[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
What I want this to be turned into is:
[[1,1,5],[1,2,4],[1,3,3],[1,4,2],[1,5,1],[2,1,4],[2,2,3],[2,3,2],[2,4,1],[3,1,3],[3,2,2],[3,3,1],[4,1,2],[4,2,1],[5,1,1]]
Basically, each term in the whole list is headed by a number, which forms the first item of all possible solutions with that number, and then the following lists indicate what is to be added.
This should work. It works with the example that you have atleast.
result = [[[i[0]] + j for j in i[1:][0] ] for i in arr][0]
items = [[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
flat_items = []
for item in items:
leading = item[0]
for i in item[1]:
flat_items.append([leading]+i)
print(flat_items)
Yet another solution that gives you an output as you needed:
def flatten(lst):
result = []
for i in lst:
for j in i[1]:
pair = j[:]
pair.insert(0, i[0])
result.append(pair)
return result
Introduce two functions: merge and flatten.
The second function is taken from here:
def flatten(lst):
return [item for sublist in lst for item in sublist]
The first function is defined as:
def merge(lst):
return [[lst[0]] + x for x in flatten(lst[1:])]
Then call them:
s = [[1, [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]], [2, [[1, 4], [2, 3], [3, 2], [4, 1]]], [3, [[1, 3], [2, 2], [3, 1]]], [4, [[1, 2], [2, 1]]], [5, [[1, 1]]]]
print flatten([merge(x) for x in s])
Output is:
[[1, 1, 5], [1, 2, 4], [1, 3, 3], [1, 4, 2], [1, 5, 1], [2, 1, 4], [2, 2, 3], [2, 3, 2], [2, 4, 1], [3, 1, 3], [3, 2, 2], [3, 3, 1], [4, 1, 2], [4, 2, 1], [5, 1, 1]]