Related
I am currently coding Conway's game of life and to add randomization to my world I have implemented a function to create a random matrix with 1 and 0 with n rows and n columns.
The problem is that, for my code to work, I need a random matrix of 1 and 0 but they have to be floats, so 0.0 and 1.0
So I cannot use:
rand_matrix = numpy.random.randint(0, 2, size=n)
Instead I have tried:
n = 10
one_zero = [0.0,1.0]
rand_matrix = np.array([n*[random.choice(one_zero),random.choice(one_zero)],n*[random.choice(one_zero),random.choice(one_zero)]])
Getting:
[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1.]]
But this returns a matrix of different dimensions, what I want is a random n by n matrix. And each row should be a combination of 0.0 and 1.0 randomly chosen.
>>> np.random.randint(0, 2, (10, 10)).astype(float)
array([[0., 0., 0., 1., 1., 0., 1., 1., 1., 1.],
[1., 1., 1., 1., 0., 1., 1., 0., 0., 1.],
[1., 0., 1., 0., 1., 1., 1., 1., 0., 0.],
[1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 0., 0., 1., 1., 1., 0., 1., 0., 1.],
[0., 1., 1., 1., 0., 0., 1., 0., 0., 0.],
[0., 1., 1., 0., 1., 0., 0., 1., 1., 0.],
[0., 0., 0., 1., 0., 0., 1., 0., 1., 0.],
[0., 1., 1., 1., 1., 1., 1., 0., 1., 1.],
[0., 1., 0., 1., 1., 1., 0., 0., 0., 0.]])
You can just cast the randint() matrix to float:
>>> import numpy as np
>>> n = 10
>>> rand_matrix = np.random.randint(0, 2, size=(n, n)).astype(float)
array([[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 1., 1., 1., 0., 0., 1., 1.],
[1., 1., 1., 1., 0., 0., 1., 1., 0., 0.],
[1., 0., 0., 1., 0., 1., 0., 1., 0., 1.],
[0., 0., 0., 0., 1., 1., 0., 1., 1., 1.],
[0., 1., 1., 1., 1., 0., 1., 1., 1., 0.],
[0., 0., 1., 0., 0., 0., 0., 1., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 1., 1., 0.],
[1., 0., 0., 0., 0., 0., 1., 1., 1., 1.],
[1., 0., 0., 1., 1., 1., 1., 1., 1., 0.]])
>>>
I'm working with 3D boolean arrays that mask a volume. My goal is to take a mask and reduce the area of the mask by some margin, m, in all dimensions.
Is there an easy way to do this using some common libraries (numpy, scipy, pandas, etc..)?
I found some code online that uses multiple for loops to expand a mask by one dimension. This works for the expansion case but I feel like there is a more compact way out there.
Here is a minimum example of what I am looking for in 2D.
Original
array([[0., 0., 1., 0., 0.],
[0., 1., 1., 1., 0.],
[1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0.],
[0., 0., 1., 0., 0.]])
Uniform reduction by 1 pixel
array([[0., 0., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 1., 1., 1., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0.]])
But I want this to be in 3D space. Thank you for any input.
You might be looking for scipy.ndimage.binary_erosion(a):
a = np.array([
[0., 0., 1., 0., 0.],
[0., 1., 1., 1., 0.],
[1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0.],
[0., 0., 1., 0., 0.]
])
b = scipy.ndimage.binary_erosion(a) # returns an array of bool
Note that this will erode internal surfaces too
I have some 2d arrays using numpy, and I want to copy subregions from one into another. For example, if I start with:
dest = numpy.zeros((4, 4))
# array([[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]])
src = numpy.ones((4, 4))
# array([[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]])
I want to somehow say that the src should be copied into dest at (2,1), such that source would then look like:
array([[0., 0., 0., 0.],
[0., 0., 1., 1.],
[0., 0., 1., 1.],
[0., 0., 1., 1.]])
Or if (-3, 0), then:
array([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])
I can do the good old fashioned double index loop to do this, but I was hoping numpy had some clever magic that did it. I looked at take, but couldn't see how to make that the tool for this job.
Both of these can be accomplished with numpy indexing. To understand how this works, the documentation is always your friend.
Your first case:
dest[1: ,2:] = src[1: ,2:]
array([[0., 0., 0., 0.],
[0., 0., 1., 1.],
[0., 0., 1., 1.],
[0., 0., 1., 1.]])
Your second case: (You indicated column -3 but your results indicate -4)
dest[:, -4] = src[:, -4]
array([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])
I want to fill a matrix from an array of indices :
import numpy as np
indx = [[0,1,2],[1,2,4],[0,1,3],[2,3,4],[0,3,4]]
x = np.zeros((5,5))
for i in range(5):
x[i,indx[i]] = 1.
The result is :
array([[ 1., 1., 1., 0., 0.],
[ 0., 1., 1., 0., 1.],
[ 1., 1., 0., 1., 0.],
[ 0., 0., 1., 1., 1.],
[ 1., 0., 0., 1., 1.]])
As desired.
Question
Is there a way to do this in pure python/numpy without looping ?
Use advanced-indexing after intialization -
x[np.arange(len(indx))[:,None], indx] = 1
My system is best described by a diagonal sparse matrix (Poisson). I have my diagonal sparse matrix, however, I want to change the boundary conditions (ie the "edges" of my matrix) to zero. It must be a common situation where a modeler wants to describe a system in a sparse diagonal matrix with distinct boundary conditions, is there a best practice for doing this?
[[0,0,0,0,..0],
[0,2,1,0,..0],
[0,1,2,1,..0],
...
[0,0,0,0,..0]]
It depends on which sparse matrix format you use. Apparently lil_matrix and dok_matrix can use slice assignments.
To construct a matrix efficiently, use either lil_matrix (recommended)
or dok_matrix. The lil_matrix class supports basic slicing and fancy
indexing with a similar syntax to NumPy arrays.
Which makes this rather easy:
In : x = scipy.sparse.lil_matrix(np.ones((6,6)))
In : x.todense()
Out:
matrix([[ 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.]])
In : x[:, 0] = 0
In : x[:, -1] = 0
In : x[0, :] = 0
In : x[-1, :] = 0
In : x.todense()
Out:
matrix([[ 0., 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0., 0.]])
PS: FYI, your matrix is called tridiagonal, not diagonal.