How can I make an n by 2^n matrix of 0 and 1 values where all the columns are distinct? For example, if n = 2 that would be
0011
0101 .
And I can use itertools to make all possible tuples.
list(itertools.product([0,1],repeat = 2))
But how do I make those the columns of my matrix?
Simply apply a np.matrix to your result:
>>> np.matrix(list(itertools.product([0,1],repeat = 2)))
matrix([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
X = numpy.array(map(lambda x: list(x), itertools.product([0,1],repeat = 2)))
Takes your itertools result and turns every element into a list and then turns it into a numpy array. If that's not the direction that you want you can then use.
X = X.transpose()
For entertainment's sake, here's a pure-numpy way of doing it:
>>> n = 2
>>> (np.arange(2**n) // ((1 << np.arange(n)[::-1,None]))) & 1
array([[0, 0, 1, 1],
[0, 1, 0, 1]])
>>> n = 4
>>> (np.arange(2**n) // ((1 << np.arange(n)[::-1,None]))) & 1
array([[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, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]])
Some explanation (note that it's very unlikely I'd ever write anything like the above in production code):
First, we get the numbers we need the bits of:
>>> np.arange(2**n)
array([0, 1, 2, 3])
Then the exponents of the powers of 2 we care about:
>>> np.arange(n)
array([0, 1])
Bitshift 1 by these to get the powers of two:
>>> 1 << np.arange(n)
array([1, 2])
Swap the order for aesthetic purposes:
>>> (1 << np.arange(n))[::-1]
array([2, 1])
Use None to introduce an extra axis, so we can broadcast:
>>> (1 << np.arange(n))[::-1, None]
array([[2],
[1]])
Divide:
>>> np.arange(2**n) // (1 << np.arange(n))[::-1, None]
array([[0, 0, 1, 1],
[0, 1, 2, 3]])
Take only the first bit:
>>> (np.arange(2**n) // (1 << np.arange(n))[::-1, None]) & 1
array([[0, 0, 1, 1],
[0, 1, 0, 1]])
Just use list comprehension:
a = list(itertools.product([0,1],repeat = n))
[[p[i] for p in a] for i in xrange(n)]
Demo:
>>> n = 2
>>> a = list(itertools.product([0,1],repeat = n))
>>> M = [[p[i] for p in a] for i in xrange(0,n)]
>>> M
[[0, 0, 1, 1], [0, 1, 0, 1]]
>>> n = 4
>>> a = list(itertools.product([0,1],repeat = 4))
>>> M = [[p[i] for p in a] for i in xrange(0,4)]
>>> M
[[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, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]]
Related
I know you can iterate over a 2d matrix using two indexes like this:
import numpy as np
A = np.zeros((10,10))
for i in range(0,10):
for j in range(0,10):
if (i==j):
A[i,j] = 4
Is there a way of doing this using only one for loop or using slices?
EDIT:
I also need to take into account of when i =/ j, for example:
A = np.zeros((10,10))
for i in range(0,10):
for j in range(0,10):
if (i==j):
A[i,j] = 1
if (i+1 ==j):
A[i,j] = 2
if (i-1==j):
A[i,j] = 3
You can always collapse multiple loops into one by calculating the components each iteration with the modulo operator like so:
import numpy as np
A = np.zeros((10,10))
for x in range(100):
i = math.floor(x/10)
j = x % 10
if (i==j):
A[i,j] = 1
if (i+1 ==j):
A[i,j] = 2
if (i-1==j):
A[i,j] = 3
With only i==j it could be even simpler:
for i in range(10):
A[i,i] = 4
In [129]: A = np.zeros((10,10), int)
...: for i in range(0,10):
...: for j in range(0,10):
...: if (i==j):
...: A[i,j] = 1
...: if (i+1 ==j):
...: A[i,j] = 2
...: if (i-1==j):
...: A[i,j] = 3
...:
You should have shown the resulting A:
In [130]: A
Out[130]:
array([[1, 2, 0, 0, 0, 0, 0, 0, 0, 0],
[3, 1, 2, 0, 0, 0, 0, 0, 0, 0],
[0, 3, 1, 2, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 1, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 3, 1, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 3, 1, 2, 0, 0, 0],
[0, 0, 0, 0, 0, 3, 1, 2, 0, 0],
[0, 0, 0, 0, 0, 0, 3, 1, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 3, 1, 2],
[0, 0, 0, 0, 0, 0, 0, 0, 3, 1]])
So you have set 3 diagonals:
In [131]: A[np.arange(10),np.arange(10)]
Out[131]: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
In [132]: A[np.arange(9),np.arange(1,10)]
Out[132]: array([2, 2, 2, 2, 2, 2, 2, 2, 2])
In [133]: A[np.arange(1,10),np.arange(9)]
Out[133]: array([3, 3, 3, 3, 3, 3, 3, 3, 3])
The key to eliminating loops in numpy is to get a big picture of the task, rather than focusing on the iterative steps.
There are various tools for making a diagonal array. One is np.diag, which can be used thus:
In [139]: np.diag(np.ones(10,int),0)+
np.diag(np.ones(9,int)*2,1)+
np.diag(np.ones(9,int)*3,-1)
Out[139]:
array([[1, 2, 0, 0, 0, 0, 0, 0, 0, 0],
[3, 1, 2, 0, 0, 0, 0, 0, 0, 0],
[0, 3, 1, 2, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 1, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 3, 1, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 3, 1, 2, 0, 0, 0],
[0, 0, 0, 0, 0, 3, 1, 2, 0, 0],
[0, 0, 0, 0, 0, 0, 3, 1, 2, 0],
[0, 0, 0, 0, 0, 0, 0, 3, 1, 2],
[0, 0, 0, 0, 0, 0, 0, 0, 3, 1]])
Or adapting [131] etc
In [140]: A = np.zeros((10,10), int)
...: A[np.arange(10),np.arange(10)]=1
...: A[np.arange(9),np.arange(1,10)]=2
...: A[np.arange(1,10),np.arange(9)]=3
Because your only executing code when i == j, you can just use:
for i in range(0,10):
A[i,i] = 4
I have a (long) list in which zeros and ones appear at random:
list1 = [1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1]
1.I want to get another list
the sum of the list up to where 0 appears
where 0 appears, retain 0 in the list
list2 = [3, 0, 2, 0, 1, 0, 3]
It should work for corner cases as well like zeroes at start or end
list1 = [0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0]
list2 = [0, 3, 0, 2, 0, 1, 0, 3, 0]
You can use itertools.groupby:
from itertools import groupby
list1 = [1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1]
out = []
for v, g in groupby(list1):
if v:
out.append(sum(g))
else:
out.extend(g) # or out.append(0) if you want to keep only single zero
print(out)
Prints:
[3, 0, 2, 0, 1, 0, 3]
For list1 = [0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0] it prints:
[0, 3, 0, 2, 0, 1, 0, 3, 0]
If you want to do it the plain-vanilla way without importing anything, you could do:
list2 = [1] if list1[0] else [0] # Initialise
for i in range(1, len(list1)):
if list1[i] and list1[i-1]:
list2[-1] += 1
elif list1[i]:
list2.append(1)
elif list1[i-1]:
list2.append(0)
For
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1]
[0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1]
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0]
this gives:
[3, 0, 2, 0, 1, 0, 3]
[0, 3, 0, 2, 0, 1, 0, 3]
[3, 0, 2, 0, 1, 0, 3, 0]
respectively.
Let's say I have a list of pattern [2, 1] and given a length = 5.
The pattern means that there are sets of 2 and 1 'ones' in the list in that order in a list of length = 5.
Also the space or 0 between successive groups has to be at least one.
What I've tried is:
for curr_col in pattern_list:
curr_pattern = curr_col
example_combo = [0] * dim0
idx, group_strt_idxs = 0, []
for num in curr_pattern :
group_strt_idxs.append(idx)
for i in range(num ):
example_combo[idx] = 1
idx += 1
if idx < dim0 and dim0 > 1:
example_combo[idx] = 0
idx += 1
print('ex', example_combo)
Please help!
The problem is to put the zeros into len(constraints_list) + 1 buckets. The first and last one can contain 0 or more zeros, the intermediate ones must contain at least one.
We generate the possible repartitions in the repartitions function. It is then easy to build the corresponding list:
from itertools import zip_longest
def repartitions(number, buckets, start=None):
if start is None:
start = []
mini = 0 # first sequence of zeros can be empty
else:
mini = 1 # others contain at least one zero
if buckets == 1:
# last bucket, we put all remaining zeros here
start = start + [number]
yield start
else:
for i in range(mini, number-buckets+3):
# we have to keep at least 1 zero for each other bucket
# except the last one.
current = start + [i]
yield from repartitions(number-i, buckets-1, current)
def permutations_with_constraints(constraints_list, length):
number_of_zeros = length - sum(constraints_list)
buckets = len(constraints_list) + 1
for rep in repartitions(number_of_zeros, buckets):
out = sum(([0]*zeros + [1]*ones
for zeros, ones in zip_longest(rep, constraints_list, fillvalue=0)), [])
yield out
Some examples:
print(list(permutations_with_constraints([1, 2], 5)))
# [[1, 0, 1, 1, 0], [1, 0, 0, 1, 1], [0, 1, 0, 1, 1]]
print(list(permutations_with_constraints([2, 3, 2], 11)))
# [[1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0],
# [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0],
# [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1],
# [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0],
# [1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1],
# [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1],
# [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0],
# [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1],
# [0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1],
# [0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1]]
Some explanations about the sum, as you asked in comments:
We have a rep list, and a one item shorter constraints list. We zip them with zip_longest and a fillvalue=0, which gives us [(rep[0], constraints[0]), (rep[1], constraints[1]), ... (rep[-1], 0)]. (It's really a generator, not a list, but this doesn't change anything to the explanation). The last 0 fills the missing value in constraints.
We then build a list from each tuple. For example, (2, 3) will give us [0, 0, 1, 1, 1]. sum then adds these lists, using [] as a start value.
Since the length of the groups of 1's are already given, the recursion can determine the placing for each:
def generate_groups(d, fill=1):
return [[fill]*i for i in d]
def all_groups(_d, _len):
def groupings(d, current = []):
if sum(not i for i in current) == d and sum(i == '*' for i in current) == len(_d):
yield current
else:
if sum(not i for i in current) < d:
yield from groupings(d, current+[0])
if not current or not current[-1]:
yield from groupings(d, current+['*'])
return [(lambda x, y:[c for h in y for c in ([h] if not h else next(x))])(iter(generate_groups(_d)), i)
for i in groupings(_len-sum(_d))]
print(all_groups([2, 1], 5))
print(all_groups([2, 3, 2], 11))
Output:
[[0, 1, 1, 0, 1], [1, 1, 0, 0, 1], [1, 1, 0, 1, 0]]
[[0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1], [0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1], [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1], [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1], [1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0], [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0], [1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0]]
This must be something that is really simple, but I could not fix it.
I want to do a matrix type transpose with native python list of list (i.e., without using numpy or pandas). Code is show following. I am having a hard time trying to figure out where it is wrong.
raw_matrix_list = [[1, 0, 1, 0, 1, 0],
[1, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 1]]
def rotate_matrix_list(raw_matrix_list):
rows = len(raw_matrix_list)
cols = len(raw_matrix_list[0])
new_matrix_list = [[0] * rows] * cols
for ii in xrange(cols):
for jj in xrange(rows):
# print str(ii) + ', ' + str(jj) + ', ' + str(rows)
new_matrix_list[ii][jj] = raw_matrix_list[rows-jj - 1][ii]
return(new_matrix_list)
rotate_matrix_list(raw_matrix_list)
The result I get is
[[1, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 0], [1, 1, 0, 0]]
What I want to get is:
[[1, 0, 1, 1], [0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0], [1, 0, 1, 1], [1, 1, 0, 0]]
===
$ python --version
Python 2.7.12 :: Anaconda 2.3.0 (x86_64)
===
update 2
Now I got the answer of how to do it in python with zip function. But I just failed to see why my code did not work.
Well, doing a transpose with vanilla lists in Python is pretty easy: use zip and the splat operator:
>>> raw_matrix_list = [[1, 0, 1, 0, 1, 0],
... [1, 0, 0, 0, 1, 0],
... [0, 0, 0, 0, 0, 1],
... [1, 0, 0, 0, 1, 1]]
>>> transpose = list(zip(*raw_matrix_list))
>>> transpose
[(1, 1, 0, 1), (0, 0, 0, 0), (1, 0, 0, 0), (0, 0, 0, 0), (1, 1, 0, 1), (0, 0, 1, 1)]
>>> from pprint import pprint
>>> pprint(transpose)
[(1, 1, 0, 1),
(0, 0, 0, 0),
(1, 0, 0, 0),
(0, 0, 0, 0),
(1, 1, 0, 1),
(0, 0, 1, 1)]
For python 2, you only need zip(*raw_matrix_list)) rather than list(zip(*raw_matrix_list)))
If a list of tuples won't do:
>>> transpose = [list(t) for t in zip(*raw_matrix_list)]
>>> pprint(transpose)
[[1, 1, 0, 1],
[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 0],
[1, 1, 0, 1],
[0, 0, 1, 1]]
The problem with your solution is that you use:
new_matrix_list = [[0] * rows] * cols
This makes every list the same object.
See this example for the problem:
>>> x = [[0]*3] * 4
>>> x
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> x[0][0] = 1
>>> x
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
Use something like:
new_matrix_list = [[0 for _ in range(rows)] for _ in range(cols)]
And you should be well on your way.
Using a nested list comprehension:
rows, cols = len(raw_matrix_list), len(raw_matrix_list[0])
>>> [[raw_matrix_list[i][j] for i in range(rows)] for j in range(cols)]
[[1, 1, 0, 1],
[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 0],
[1, 1, 0, 1],
[0, 0, 1, 1]]
There are already answers that help solve your problem. As to why your code doesn't work, shouldn't it be this (by definition of matrix transpose):
new_matrix_list[ii][jj] = raw_matrix_list[jj][ii]
I'm trying to generate all possible bytes to test for a machine learning algorithm (8-3-8 mural network encoder). is there a way to do this in python without having 8 loops?
Could permutations help?
I'd prefer an elegant way to do this, but I'll take what I can get at the moment.
desired output:
[0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,1]
[0,0,0,0,0,0,1,0]
[0,0,0,0,0,0,1,1]
[0,0,0,0,0,1,0,0]
[0,0,0,0,0,1,0,1]
.
.
.
[1,1,1,1,1,1,1,1]
Yes, there is, itertools.product:
import itertools
itertools.product([0, 1], repeat=8)
>>> list(itertools.product([0, 1], repeat=8))
[(0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 1),
[...]
(1, 1, 1, 1, 1, 1, 1, 0),
(1, 1, 1, 1, 1, 1, 1, 1)]
[[x>>b&1 for b in range(8)] for x in range(256)]
You could iterate over the numbers and then convert to binary:
[bin(x)[2:] for x in range(256)]
If you happen to be using numpy already...
In [48]: import numpy as np
In [49]: nbits = 4
In [50]: np.sign(np.bitwise_and(2 ** np.arange(nbits), np.arange(2 ** nbits).reshape(-1, 1)))
Out[50]:
array([[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 1, 0, 0],
[1, 1, 0, 0],
[0, 0, 1, 0],
[1, 0, 1, 0],
[0, 1, 1, 0],
[1, 1, 1, 0],
[0, 0, 0, 1],
[1, 0, 0, 1],
[0, 1, 0, 1],
[1, 1, 0, 1],
[0, 0, 1, 1],
[1, 0, 1, 1],
[0, 1, 1, 1],
[1, 1, 1, 1]])