Producing binary matrix with random lists - python

so first of all here is my code I have questions about, I feel like the answer will be simple, but I am just too blind to see it
dic = {}
for i in range(0,9):
dic['rand_num{0}'.format(i)] = np.sort(random.sample(range(0,8),5))
mat = np.zeros([8,8])
for rand_num in dic.values():
print(rand_num)
for i in range(0,5):
matrixval = rand_num[i]
#print(matrixval)
for j in range(0,8):
mat[matrixval,j] = 1
print(mat)
I created 8 different lists which will help me determine, where to set a 1 in the matrix.
so eg. if my first list looks like this:
rand_List = [0,3,5,6,7]
the matrix of the first row or column should look like this
matrix = [1, 0, 0, 1, 0, 1, 1, 1]
My position for the matrix value is set in the second loop: for i in range(0,5): matrixval = rand_num[i] . However, as soon I run my code, my matrix just gives me ones instead of ones and zeros. I feel like I have an iteration problem in my last for loop, and I don't know how to fix it.
If anyone could help me, or just give me a hint, how to actually solve this hopefully small mistake of mine, I would really appreciate it.

Hopefully this provides the expected result:
dic = {}
for i in range(0,8):
dic['rand_num{0}'.format(i)] = np.sort(random.sample(range(0,8),5))
mat = np.zeros([8,8])
for j, rand_num in enumerate(dic.values()):
print(rand_num)
for i in range(0,5):
matrixval = rand_num[i]
mat[j,matrixval] = 1
print(mat)
Output:
[1 2 3 5 7]
[0 1 2 5 6]
[0 1 2 3 5]
[1 2 3 4 6]
[0 1 3 4 7]
[1 2 4 5 7]
[0 1 3 4 7]
[1 2 3 4 6]
[[0. 1. 1. 1. 0. 1. 0. 1.]
[1. 1. 1. 0. 0. 1. 1. 0.]
[1. 1. 1. 1. 0. 1. 0. 0.]
[0. 1. 1. 1. 1. 0. 1. 0.]
[1. 1. 0. 1. 1. 0. 0. 1.]
[0. 1. 1. 0. 1. 1. 0. 1.]
[1. 1. 0. 1. 1. 0. 0. 1.]
[0. 1. 1. 1. 1. 0. 1. 0.]]

The dic you are using is not needed. Here is a solution without it.
import random
lists = []
for i in range(0, 9):
lists.append(sorted(random.sample(range(0, 8), 5)))
mat = []
for lst in lists:
arr = [0] * 8
for index in lst:
arr[index] = 1
mat.append(arr)
print(mat)
Outputs:
[[0, 1, 1, 0, 0, 1, 1, 1],
[1, 0, 1, 1, 0, 0, 1, 1],
[1, 1, 1, 1, 0, 0, 0, 1],
[0, 1, 1, 1, 0, 1, 1, 0],
[1, 1, 0, 1, 1, 0, 1, 0],
[1, 0, 1, 1, 0, 1, 1, 0],
[0, 1, 1, 1, 1, 1, 0, 0],
[0, 1, 1, 0, 1, 1, 1, 0],
[1, 0, 1, 0, 1, 0, 1, 1]]
You can also use numpy.random.randint to generate your binary 2d array.
import numpy as np
arr = np.random.randint(2, size=(8, 8))
print(arr)
Outputs:
[[1 0 1 0 1 0 1 1]
[0 0 0 0 1 0 1 1]
[1 0 1 1 0 0 1 1]
[1 1 0 1 0 1 1 0]
[0 0 1 0 0 1 1 1]
[1 0 0 0 1 1 1 1]
[1 1 0 1 0 0 1 1]
[1 0 1 0 0 1 0 0]]

Related

Add the same value to every row in a numpy array

I have a numpy array that looks like this:
[[0.67058825 0.43529415 0.33725491]
[0.01568628 0.30980393 0.96862751]
[0.24705884 0.63529414 0.29411766]
[0.27843139 0.63137257 0.37647063]
[0.26274511 0.627451 0.33333334]
[0.25098041 0.61960787 0.30980393]]
I want to add a 1 to every row like this:
[[0.67058825 0.43529415 0.33725491 1]
[0.01568628 0.30980393 0.96862751 1]
[0.24705884 0.63529414 0.29411766 1]
[0.27843139 0.63137257 0.37647063 1]
[0.26274511 0.627451 0.33333334 1]
[0.25098041 0.61960787 0.30980393 1]]
Simply with numpy.insert to insert the needed value into required position along the given axis:
arr = np.insert(arr, arr.shape[1], 1, axis=1)
[[0.67058825 0.43529415 0.33725491 1. ]
[0.01568628 0.30980393 0.96862751 1. ]
[0.24705884 0.63529414 0.29411766 1. ]
[0.27843139 0.63137257 0.37647063 1. ]
[0.26274511 0.627451 0.33333334 1. ]
[0.25098041 0.61960787 0.30980393 1. ]]
Assuming a the input, you can try:
out = np.c_[a, np.ones((a.shape[0], 1))]
Or:
out = np.hstack([a, np.ones((a.shape[0], 1))])
Output:
array([[0.67058825, 0.43529415, 0.33725491, 1. ],
[0.01568628, 0.30980393, 0.96862751, 1. ],
[0.24705884, 0.63529414, 0.29411766, 1. ],
[0.27843139, 0.63137257, 0.37647063, 1. ],
[0.26274511, 0.627451 , 0.33333334, 1. ],
[0.25098041, 0.61960787, 0.30980393, 1. ]])
You can do this:
arr = [ [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0] ]
to_add = [1 for i in range(0, len(arr)) #Making array with all 1s
x = np.column_stack((arr, to_add)) #Add columns together
print(x)
Returns:
[[0 0 0 0 1]
[0 0 0 0 1]
[0 0 0 0 1]]

How to "zero" all entries in an array with an equal adjacent entry?

I have a large array of 1's and 0's. Each time a 1 appears in it, I want to make sure that all the 1's adjacent (or diagonal) to that 1 are set to 0 - so that the array you are left with has one 1 for every "group" of ones that appeared in the original array (I don't mind which 1 is kept per group, just as long as there are no adjacent/neighbouring 1's).
For example, with the following array (much smaller than what I will be dealing with, but I want to illustrate the problem).
[[0. 0. 0. 1.]
[0. 1. 0. 0.]
[0. 1. 0. 0.]
[1. 0. 0. 1.]
[0. 0. 1. 0.]]
I would want to return an array that looks like:
[[0. 0. 0. 1.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[1. 0. 0. 0.]
[0. 0. 1. 0.]]
I have tried the following code for the above array (which is labelled as a) in order to achieve this:
# Define a function which finds if an entry has a 1 neighbouring it
def has_neighbour(matrix, x, y):
if matrix[x-1,y]==1 or matrix[x+1,y]==1 or matrix[x, y+1]==1 or matrix[x, y-1]==1 or matrix[x+1, y+1]==1 or matrix[x+1, y-1]==1 or matrix[x-1, y+1]==1 or matrix[x-1, y-1]==1:
# Find the entries in the matrix of 1 and if they have an adjacent 1, set them to zero
for i in range(4):
for j in range(3):
if a[i,j]==0 or (a[i,j] == 1 and has_neighbour(a, i, j)==True):
a[i,j] = 0
else:
a[i,j] = 1
# Re-search along the last row and column for adjacent 1's, setting them to zero where necessary. This is needed due to for loops not changing the last row and column of an array
for i in range(4):
if a[i,3]==0 or (a[i,3]==1 and (a[i+1,3]==1 or a[i-1,3]==1)):
a[i,3] = 0
else:
a[i,3]=1
for j in range(3):
if a[4, j]==0 or (a[4, j]==1 and (a[4, j+1]==1 or a[4, j-1]==1)):
a[4, j] = 0
else:
a[4, j] = 1
However, this code returns the following array:
[[0. 0. 0. 1.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 1.]
[0. 0. 1. 0.]]
Anyone know what I is going wrong here? I am very confused as it's getting rid of some 1's I don't want it to and not getting rid of some that I do want it to.
Edit
#JohnColeman's answer is the closest to working so far. However, it fails on the following matrix (I've attached his code, but changed the test part to the matrix that it is failing with):
def pick_reps(matrix):
m = len(matrix)
n = len(matrix[0])
reps = [[0]*n for _ in range(m)]
represented = set()
for i, row in enumerate(matrix):
for j,x in enumerate(row):
if x == 1:
#check if this position is in an already represented block
covered = False
if j > 0 and (i,j-1) in represented:
covered = True
elif i > 0 and (i-1,j) in represented:
covered = True
elif i > 0 and j > 0 and (i-1,j-1) in represented:
covered = True
elif i > 0 and j < n and (i-1,j+1) in represented:
covered = True
if not covered:
reps[i][j] = 1
represented.add((i,j))
return reps
#test:
matrix = [[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 1, 0],
[1, 0, 1, 1],
[0, 0, 0, 1]]
reps = pick_reps(matrix)
for row in reps: print(row)
This should return a matrix with only one 1 in it. However, it returns:
[[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
I think your is_neighbo(u)r1 function still needs some work. There is a lot of logic down the line that should in fact be part of that function; in particular, the borderline cases should be accounted for inside the function. Here's one way to implement your idea:
def has_neighbor(matrix, x, y):
"""Return True if any of the neighboring cells are equal to 1"""
# just in case you need to change this value at some point
value = 1
# Define neighbors to check
corners = [(-1, -1),
(0, -1),
(1, -1),
(1, 0),
(1, 1),
(0, 1),
(-1, 1),
(-1, 0)]
# get the boundaries of the matrix
x_max, y_max = matrix.shape
# for each neighbor
for x_off, y_off in corners:
# get the new coordinates to check
x2 = x+x_off
y2 = y+y_off
# skip coordinates that are out of bounds
out_of_grid = [x2 < 0,
y2 < 0,
x2 >= x_max,
y2 >= y_max]
if any(out_of_grid):
continue
# finally!
if matrix[x2, y2] == value:
return True
It can now handle the borderline cases, which makes the final loop much simpler:
x_max, y_max = a.shape
for x in range(x_max):
for y in range(y_max):
if has_neighbor(a, x, y):
a[x, y] = 0
The output is as desired:
array([[0, 0, 0, 1],
[0, 0, 0, 0],
[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 0, 1, 0]])
1 NB: In code, American spelling is more common.
This probably isn't very idiomatic, but you could iterate through the array - when you find a 1 you call a recursive function to clear all reachable 1s. This of course will clear the initial, representative element, so you set that back to 1.
a = [[0, 0, 0, 1],
[0, 1, 0, 0],
[0, 1, 0, 0],
[1, 0, 0, 1],
[0, 0, 1, 0]]
def clear(a, r, c):
if r < 0 or r == len(a) or c < 0 or c == len(a[0]) or a[r][c] == 0:
return
a[r][c] = 0
for i in [-1, 0, 1]:
for j in [-1, 0, 1]:
clear(a, r+i, c+j)
for r in range(len(a)):
for c in range(len(a[0])):
if a[r][c] == 1:
clear(a, r, c)
a[r][c] = 1
for row in a: print(row)
Output:
[0, 0, 0, 1]
[0, 1, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 1]
[0, 0, 0, 0]

How to create a lower diagonal matrix with numpy?

How can I generate a lower diagonal matrix of dynamic size with Numpy?
For example, if the size n of the matrix is 4 I would like to obtain such a matrix:
| 0 0 0 0 |
| 1 0 0 0 |
| 0 1 0 0 |
| 0 0 1 0 |
You could create it, by first creating a matrix with zeros, and then fill in the ones:
import numpy as np
# create matrix with zeros
n=4
mat = np.zeros((n,n))
# create indexes for where the 1s belong
rows = np.arange(1,n)
cols = np.arange(n-1)
# fill in the 1s
mat[rows, cols] = 1
output:
[[0. 0. 0. 0.]
[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]]
I found out the shortest way to be using np.eye:
import numpy as np
n = 4
np.eye(n, k=-1, dtype=int)
The output is:
array([[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0]])

Transform an array of count data into a matrix of ones and zeroes

I have an array n of count data, and I want to transform it into a matrix x in which each row contains a number of ones equal to the corresponding count number, padded by zeroes, e.g:
n = [0 1 3 0 1]
x = [[ 0. 0. 0.]
[ 1. 0. 0.]
[ 1. 1. 1.]
[ 0. 0. 0.]
[ 1. 0. 0.]]
My solution is the following, and is very slow. Is it possible to do better?
n = np.random.poisson(2,5)
max_n = max(n)
def f(y):
return np.concatenate((np.ones(y), np.zeros(max_n-y)))
x = np.vstack(map(f,n))
Here's one way to vectorize it:
>>> n = np.array([0,2,1,0,3])
>>> width = 4
>>> (np.arange(width) < n[:,None]).astype(int)
array([[0, 0, 0, 0],
[1, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 0],
[1, 1, 1, 0]])
where if you liked, width could be max(n) or anything else you chose.
import numpy as np
n = np.array([0, 1, 3, 0, 1])
max_n = max(n)
np.vstack(n > i for i in range(max_n)).T.astype(int) # xrange(max_n) for python 2.x
Output:
array([[0, 0, 0],
[1, 0, 0],
[1, 1, 1],
[0, 0, 0],
[1, 0, 0]])

Remove Decimals from Array

I have 2 arrays containing zeros & ones. I want to perform hstack() on them but not getting the desired output.
Python Code..
import numpy as np
zeros = np.zeros(8)
ones = np.ones(8)
zerosThenOnes = np.hstack((zeros, ones)) # A 1 by 16 array
Current Output..
[ 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1.]
Expected Output..
[ 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 ]
I can't understand what silly mistake I'm doing.
You must tell numpy to return the values as integers
import numpy as np
zeros = np.zeros((8,), dtype=np.int)
ones = np.ones((8,), dtype=np.int)
zerosThenOnes = np.hstack((zeros, ones))
To print out zerosThenOnes like this [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
Use:
print([x for x in zerosThenOnes])
Numpy Zeros
np.hstack((np.zeros(8), np.ones(8))).astype(int)
for np.array output, or
map( int, np.hstack((np.zeros(8), np.ones(8))) )
for list output

Categories