Related
Hi guys i have this problem:
I have a list with number
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
Every time i found 0 i need to count it and know his position, but when the 0 is consecutive it count as one, for example:
Position start 5, Position end 8, Count 1
Position start 12, Position end 12, Count 2
Position start 14, Position end 14, Count 3
Position start 26, Position end 31, Count 4
This can be solved like this
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
last_was_0=False
zero_clusters=[]
for i in range(len(a)):
b=a[i]
if b==0:
if last_was_0:
zero_clusters[-1][-1]+=1
else:
zero_clusters.append([i, i])
last_was_0 = b==0
for i in range(len(zero_clusters)):
print(f'Position start {zero_clusters[i][0]}, Position end {zero_clusters[i][1]}, Count {i+1}')
but if i want to try it on two list? So doing the same thing that i do with one list but having two, and checking if the current index(the same for the two list) if are both 0
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
b= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
How can I achive the result?
I have already tried like this but it gives me as result only the first iteraction
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
b= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
last_was_0=False
zero_clusters=[]
for i in range(len(a)):
b=a[i]
c=b[i]
if b==0 and c==0:
if last_was_0:
zero_clusters[-1][-1]+=1
else:
zero_clusters.append([i, i])
last_was_0 = b==0
for i in range(len(zero_clusters)):
print(f'Position start {zero_clusters[i][0]}, Position end {zero_clusters[i][1]}, Count {i+1}')
Can someone help me achieve the same result of one list but with two??
You can iterate over the lists together uzing zip, and then use itertools groupby to group consecutive values.
Looping over that and storing the indexes where the key of the group is (0,0) will get you the result you want.
from itertools import groupby
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
b= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
zero_cluster = []
i = 0
for g, d in groupby(zip(a,b)):
data = list(d)
if g!=(0,0):
i+=len(data)
else:
zero_cluster.append((i, i+len(data)-1))
i+=len(data)
for i, cluster in enumerate(zero_cluster):
print(f'Position start {cluster[0]}, Position end {cluster[1]}, Count {i+1}')
Output
Position start 5, Position end 8, Count 1
Position start 12, Position end 12, Count 2
Position start 14, Position end 14, Count 3
Position start 16, Position end 16, Count 4
Position start 28, Position end 33, Count 5
Position start 36, Position end 36, Count 6
Position start 38, Position end 38, Count 7
Position start 40, Position end 40, Count 8
Also it might be helpful to understand what itertools groupby is doing by looking at this:
for g, d in groupby(zip(a,b)):
print(g,list(d))
Prints
(1, 1) [(1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]
(0, 0) [(0, 0), (0, 0), (0, 0), (0, 0)]
(1, 1) [(1, 1), (1, 1), (1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]
(0, 0) [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
(1, 1) [(1, 1), (1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
a numpy version
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
import numpy as np
def get_clusters(lst):
arr=np.array(lst)
diff=arr[:-1]-arr[1:]
starts = np.where(diff==1)
ends = np.where(diff==-1)
indices = np.vstack((starts[0]+1, ends[0])).T
return indices, diff[diff==1].size
print(get_clusters(a))
output
(array([[ 5, 8],
[12, 12],
[14, 14],
[16, 16],
[28, 33],
[36, 36],
[38, 38],
[40, 40]]), 8)
zip() is your friend when you need to compare elements of a list with it's predecessor or successor.
So you can use zip to get the starting index of each cluster of 1s and 0s. Then use zip again to combine these indexes into ranges of positions, selecting only the ranges that contain zeros.
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
breaks = [i for i,(n,m) in enumerate(zip(a,a[1:]),1) if n!=m ]
positions = [ (s,e-1) for s,e in zip([0]+breaks,breaks+[len(a)]) if not a[s] ]
count = sum(e-s+1 for s,e in positions)
print(positions)
[(5, 8), (12, 12), (14, 14), (16, 16), (28, 33), (36, 36), (38, 38), (40, 40)]
print(count)
16
For two lists, you can combine them (using zip again) and apply the same solution:
x= [1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
y= [1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
a = [ paired != (0,0) for paired in zip(x,y) ]
breaks = [i for i,(n,m) in enumerate(zip(a,a[1:]),1) if n!=m ]
positions = [ (s,e-1) for s,e in zip([0]+breaks,breaks+[len(a)]) if not a[s] ]
count = sum(e-s+1 for s,e in positions)
print(positions)
[(5, 8), (12, 12), (14, 14), (16, 16), (28, 33), (36, 36), (38, 38), (40, 40)]
print(count)
16
If you're okay with using a library, this can be somewhat shortened using groupby from itertools:
from itertools import groupby
positions = [ (lg[0],lg[-1])
for bit,g in groupby(range(len(a)),lambda i:a[i]) if not bit
for lg in [list(g)]]
count = sum(e-s+1 for s,e in positions)
I have two elements, let's say [0,1] and I want to construct all possible combinations of length 2k with the same number of these two elements. For example, let 2k=6 and our output should be like (0,0,0,1,1,1) ,(0,0,1,0,1,1),(1,1,1,0,0,0) etc.
I was trying to use something like this [x for x in itertools.product([1,0], repeat=6)] but it gives me all possible sequences(the number of ones and zeros may not be the same). Is it possible to somehow immediately create a list with a given property?
Try itertools.permutations, like below:
import itertools
def perms(k):
l=k//2*[1] + k//2 * [0]
m=[i for i in itertools.permutations(l)]
return list(set(m))
Output for k=6:
>>> perms(6)
[(0, 1, 1, 0, 0, 1), (0, 1, 0, 1, 1, 0), (0, 1, 0, 0, 1, 1), (1, 1, 0, 0, 1, 0), (1, 1, 1, 0, 0, 0), (1, 0, 1, 0, 1, 0), (0, 0, 0, 1, 1, 1), (1, 0, 0, 1, 0, 1), (0, 1, 1, 0, 1, 0), (0, 0, 1, 1, 0, 1), (1, 1, 0, 1, 0, 0), (0, 1, 0, 1, 0, 1), (1, 1, 0, 0, 0, 1), (1, 0, 1, 1, 0, 0), (1, 0, 0, 0, 1, 1), (1, 0, 1, 0, 0, 1), (0, 0, 1, 0, 1, 1), (1, 0, 0, 1, 1, 0), (0, 1, 1, 1, 0, 0), (0, 0, 1, 1, 1, 0)]
The code can be adjusted to work with more general structures (more elements, other than [0,1] etc. Let me know if you need any help with that.
Saying a list of length 2k with equal number of elements [a, b] is equivalent to saying you want to a list with a in k positions and b in the other. So we can generate a list full of a's or b's and find all the possible combinations how to put k elements of the other variable in this list. This set of possible combinations is the same as selecting a set of k indices from the range [0, ..., 2k]. For the mathematics around this see [1].
from itertools import combinations
k = 6
assert k // 2
a = 0
b = 1
l = [
[a if i in combination else b for i in range(k)]
for combination in combinations(range(k), int(k/2))
]
[1] https://en.wikipedia.org/wiki/Combination
I am trying to loop over a 3d matrix and access the values and get some count values for finding probability. I am successful in it but one thing is i am assuming b=0 initially which i dont want to since it gives a small error in my probability which i want to reduce. the matrix is
array([[[ 1, 1, 1, 1, -99, -99],
[ 1, 1, 1, 1, -99, -99],
[ 1, 1, 1, 1, -99, -99],
[ 1, 1, 1, 1, 1, -99]],
[[-99, -99, -99, -99, -99, -99],
[-99, -99, -99, -99, -99, -99],
[-99, -99, -99, -99, -99, 1],
[-99, -99, -99, -99, -99, 1]],
[[ 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1]],
[[ 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1]]], dtype=int16)
and the code i ran is:
for i in range(4):
... for j in range(6):
... b=NR=NN=RR=RN=0
... for k in range(4):
... a = array[k][i][j]
... if(a==0 and b==0):
... NN+=1
... b=a
... elif(a==0 and b==1):
... RN+=1
... b=a
... elif(a==1 and b==0):
... NR+=1
... b=a
... elif(a==1 and b==1):
... RR+=1
... b=a
... else:
... exit
... print(NN,NR,RN,RR)
for this i get extra 24 'NR' values which i dont want to occur by not initializing b. When i did not initialize b i got the following output:
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 2)
(0, 0, 0, 2)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 2)
(0, 0, 0, 2)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 2)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
(0, 0, 0, 3)
which is not correct because the actual output is
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 1)
(0, 1, 0, 1)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 1)
(0, 1, 0, 1)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 1)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
(0, 1, 0, 2)
without the value '1' in the second column. Any suggestions on how i can solve this?
To skip a loop iteration use continue not exit (which is not a valid command). Since on the first iteration there is no valid b value, initialize it to -99. Skip summation and the b=a assignment if a=-99 so that b retains the last valid a value.
for i in range(4):
for j in range(6):
NR=NN=RR=RN=0
b = -99
for k in range(4):
a = array[k][i][j]
if a == -99 : continue
if(a == 0 and b == 0): NN+=1
elif(a == 0 and b == 1): RN+=1
elif(a == 1 and b == 0): NR+=1
elif(a == 1 and b == 1): RR+=1
b=a
print(NN,NR,RN,RR)
l have the following input list composed of values which varies from k=0 to 4:
vector_input= [(3, 3, 3, 3, 3), (0, 0, 1), (3, 4, 3, 3, 4, 4), (1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 3, 3, 3, 1, 1, 3), (0, 0), (4, 4, 4, 4, 4), (1, 1), (3, 3), (1, 4, 3, 2), (3, 3, 4, 4, 4), (4, 4, 4, 4, 4), (3,), (2, 2), (2, 2, 2, 2, 2, 2), (0, 0, 0, 0, 1, 0), (1, 1, 1, 1, 1), (1, 1, 1, 1, 1), (0, 0, 0, 0, 0, 0, 1, 0, 0, 1)]
l want to transform this list into a list of frequency output of dimension of k (k=4) so that to get list output as follows :
vector_output=[
[0,0,0,5,0],[2,1,0,0,0],[0,0,0,3,3],[0,4,0,0,0],[0,16,0,0,0], [0,3,0,4,0],
[2,0,0,0,0],[0,0,0,0,5],[0,0,0,3,0],[0,0,2,0,0],[0,0,6,0,0],[5,1,0,0,0],[0,5,0,0,0],[0,5,0,0,0],[8,2,0,0,0]]
For instance : (3, 3, 3, 3, 3) becomes (0,0,0,5,0) because three is repeated five times and 0,1,2,4 zero times.
You could create a distribution function:
def distribution(vector, highest=5):
dist = [0] * highest
for i in vector:
dist[i] += 1
return dist
and apply it to every vector with a list comprehension:
vector_input= [(3, 3, 3, 3, 3), (0, 0, 1), (3, 4, 3, 3, 4, 4), (1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 3, 3, 3, 1, 1, 3), (0, 0), (4, 4, 4, 4, 4), (1, 1), (3, 3), (1, 4, 3, 2), (3, 3, 4, 4, 4), (4, 4, 4, 4, 4), (3,), (2, 2), (2, 2, 2, 2, 2, 2), (0, 0, 0, 0, 1, 0), (1, 1, 1, 1, 1), (1, 1, 1, 1, 1), (0, 0, 0, 0, 0, 0, 1, 0, 0, 1)]
print([distribution(v) for v in vector_input])
# [[0, 0, 0, 5, 0], [2, 1, 0, 0, 0], [0, 0, 0, 3, 3], [0, 4, 0, 0, 0], [0, 16, 0, 0, 0], [0, 3, 0, 4, 0], [2, 0, 0, 0, 0], [0, 0, 0, 0, 5], [0, 2, 0, 0, 0], [0, 0, 0, 2, 0], [0, 1, 1, 1, 1], [0, 0, 0, 2, 3], [0, 0, 0, 0, 5], [0, 0, 0, 1, 0], [0, 0, 2, 0, 0], [0, 0, 6, 0, 0], [5, 1, 0, 0, 0], [0, 5, 0, 0, 0], [0, 5, 0, 0, 0], [8, 2, 0, 0, 0]]
You can try this:
import itertools
vector_input= [(3, 3, 3, 3, 3), (0, 0, 1), (3, 4, 3, 3, 4, 4), (1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 3, 3, 3, 1, 1, 3), (0, 0), (4, 4, 4, 4, 4), (1, 1), (3, 3), (1, 4, 3, 2), (3, 3, 4, 4, 4), (4, 4, 4, 4, 4), (3,), (2, 2), (2, 2, 2, 2, 2, 2), (0, 0, 0, 0, 1, 0), (1, 1, 1, 1, 1), (1, 1, 1, 1, 1), (0, 0, 0, 0, 0, 0, 1, 0, 0, 1)]
full_listing = list(set(itertools.chain(*vector_input)))
final_data = [tuple(list(b).count(c) for c in range(min(full_listing), max(full_listing)+1)) for b in vector_input]
Output:
[(0, 0, 0, 5, 0), (2, 1, 0, 0, 0), (0, 0, 0, 3, 3), (0, 4, 0, 0, 0), (0, 16, 0, 0, 0), (0, 3, 0, 4, 0), (2, 0, 0, 0, 0), (0, 0, 0, 0, 5), (0, 2, 0, 0, 0), (0, 0, 0, 2, 0), (0, 1, 1, 1, 1), (0, 0, 0, 2, 3), (0, 0, 0, 0, 5), (0, 0, 0, 1, 0), (0, 0, 2, 0, 0), (0, 0, 6, 0, 0), (5, 1, 0, 0, 0), (0, 5, 0, 0, 0), (0, 5, 0, 0, 0), (8, 2, 0, 0, 0)]
I am trying to generate a list of length n from two possible items. e.g. One example could be, a list of length 4 comprising zeros or ones which would be 0000, 0001, 0010, 0100, 1000, 1001, etc.
Thanks in advance,
Jack
With itertools.product:
In [1]: from itertools import product
In [2]: list(product((0, 1), repeat=4))
Out[2]:
[(0, 0, 0, 0),
(0, 0, 0, 1),
(0, 0, 1, 0),
(0, 0, 1, 1),
(0, 1, 0, 0),
(0, 1, 0, 1),
(0, 1, 1, 0),
(0, 1, 1, 1),
(1, 0, 0, 0),
(1, 0, 0, 1),
(1, 0, 1, 0),
(1, 0, 1, 1),
(1, 1, 0, 0),
(1, 1, 0, 1),
(1, 1, 1, 0),
(1, 1, 1, 1)]
You can also just print ints as binary strings:
In [3]: for i in range(2**4):
...: print('{:04b}'.format(i))
...:
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Check out the product function from the itertools module: https://docs.python.org/2/library/itertools.html#itertools.product
from itertools import product
product(range(2), repeat=4)
# --> <itertools.product object at 0x10bdc1500>
list(product(range(2), repeat=4))
# --> [(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 1, 0), (0, 1, 1, 1), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0), (1, 0, 1, 1), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 1, 0), (1, 1, 1, 1)]