random numbers between 1 and -1 in a 2D lattice - python

I have to make an assignment called "The 2D Grid" if you have heard of it?
The first task is to make a 2D lattice, and the question goes:
Come up with a way to define a square 2D list (or Numpy array) containing randomly distributed values of -1 or 1.
I have used this:
np.random.randint(1, size = (6,6))
but how can I get numbers between 1 and -1 ?

Related

How to avoid for-loop while using append()

First of all, I apologize for being an absolute beginner in both python and numpy. Please forgive my ignorance.
I have a 4D cube of pressure measurements where the dimensions are (number of samples, time, y-axis, x-axis), which means, for each sample, I have a 3D cube of spatio-temporal profile. I need to collect the pressure readings of this 3D cube (time, y-axis, x-axis) and store it into an array for each sample only where the coordinates satisfy a specific condition. Upon varying the specific condition, the size of this array will vary too. So, I have to use append() to build this array. However, since say for 1000 samples, I have to search through more than a millions coordinates using For-Loop for each sample, the code I have written is pretty inefficient and takes a lot of time to run (more than several hours). Can you please help me to write it more efficiently?
Below is the code I've tried to solve the problem. It works nicely and gives expected result but it is extremely slow.
import numpy as np
# Number of sample points in x,y and t-axis
Nx = 101
Ny = 101
Nt = 100
n_train = 1000
target_array = []
for i_train in range (n_train):
for k in range (Nt):
for j in range (Ny):
for i in range (Nx):
if np.round(np.sqrt((i-np.round(Nx/2))**2+(j-np.round(Ny/2))**2)) == 2*k:
target_array.append(Pressure[i_train,k,j,i])
Since the condition involves the indexes and not the values of your 4D array, you can vectorize it using numpy.meshgrid.
Here pp is your 4D array:
iv, jv, kv = np.meshgrid(np.arange(pp.shape[3]), np.arange(pp.shape[2]), np.arange(pp.shape[1]))
selecting = np.round(np.sqrt((iv - np.round(pp.shape[3]/2))**2 + (jv - np.round(pp.shape[2]/2))**2)) == 2*kv
target = pp[:,selecting]
Provided that I've understood correctly how your 4D array is organized:
the arrays created by meshgrid hold the indexes to select pp elements on the 3 dimensions x, y, t.
selecting is a boolean array created by replicating your equation, to check which coordinates satisfies the condition.
target is a selection of pp, taking all element on 0 axis which satisfies the condition (i.e. selecting is True) on the other 3 axes.
Note that target is a 2D array, to have a 1D array, use target.flatten().

Numpy generate binary array with at most N ones

I can easily create a random binary array in Numpy by doing this
random_mask = np.random.randint(0,2, (r, c))
But what what I actually want is to set the maximum number of 1s that can be in the array.
For example, if I want a 5,5 binary matrix, I want there to be at most 10 ones randomly placed throughout the matrix, and the rest are 0s.
I was thinking of an approach where I generate the random array like normal, count the number of 1s that are currently placed, and somehow subtracting off the ones I don't need.
I'm wondering if there's already a way to do this in numpy
This is the most basic approach I could think of:
import numpy as np
def binary_mask_random(r, c, n):
a = np.zeros((r,c)).flatten()
for i in range(np.random.randint(0, n+1)):
x = np.random.randint(0, r*c)
a[x] = 1
return a.reshape((r,c))
It creates a 1xr*c array of zeros and fills it with up to n 1s at random positions. Returns a rxc array.

How to assign values of a 2d array to 3d array in NumPy

I'm currently working on a 3d array called X of size (100,5,1). I want to assign the randomly created 2d arrays called s, dimension of (5,1) to X. My code is like below.
for i in range(100):
s = np.random.uniform(-1, 2, 5)
for j in range(5):
X[:,j,:] = s[j]
I got 100 (5,1) arrays and they're all the same. I can see why I have this result, but I can't find the solution for this.
I need to have 100 unique (5,1) arrays in X.
You are indexing the entire first dimension and thus broadcasting a single 5 x 1 array. This is why you are seeing copies and it only remembers the last randomly generated 5 x 1 array you've created in the loop seen over the entire first dimension. To fix this, simply change the indexing from : to i.
X[i,j,:] = s[j]
However, this seems like a bad code smell. I would recommend allocating the exact size you need in one go by overriding the size input parameter into numpy.random.uniform.
s = np.random.uniform(low=-1, high=2, size=(100, 5, 1))
Therefore, do not loop and just use the above statement once. This makes sense as each 5 x 1 array you are creating is sampled from the same probability distribution. It would make more sense in an efficiency viewpoint to just allocate the desired size once.

generate matrix with np.zeros Python - Matrix must be 2 dimensinonal error

Hey I want to generate a zero matrix. Therefore my idea is using 3 zerovectors. Unfortunately I get the error:
"matrix must be 2-dimensional"
here is my code:
dx=0.5
dy=0.5
dz=0.5
npoints = 9 #count of total x-values
x=np.arange(-2.,2.1,dx)
y=np.arange(-2.,2.1,dy)
z=np.arange(-2.,2.1,dz)
M=np.matrix(([x,y,z]))
print M
print
print
Vx= np.zeros((1, npoints))
print Vx
Vy=np.zeros((1,npoints))
Vz=np.zeros((1,npoints))
V=np.matrix(([Vx,Vy]))
I get the error at the second matrix. What is my mistake ;)
You are creating a matrix from a three-dimensional array, because Vx and Vy are already two-dimensional by the way you created them (although one axis has length 1). There are several possible remedies such as creating Vx et al. one-dimensional:
Vx=np.zeros(npoints)
or creating your matrix directly
V=np.matrix(np.zeros(2,npoints))
And probably many others.
Note that your error in understanding may be that np.zeros takes a shape as input not some kind of coordinate range. So you can just create an array of whatever shape you want directly with np.zeros. The above call for example generates a 2xnpoints matrix.

Interpolate Array to a New Length | Python

Given an array of values say 300x80, where 300 represents the # of samples and 80 represents the features you want to keep.
I know in MATLAB and Python you can do interp1d and such, but I don't think that works for me in this situation. All I could find are 1D examples.
Is there a way to do interpolation to make this array say 500x80 in Python?
Simple question of 300x80 -> 500x80.
http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp2d.html
x, y are your matrix indices (row/column index), and z is the value at that position. It returns a function that you can call on all points of a new 500x80 grid.
Of course it does not make any sense, since they are sample/variable indices and it just means inventing more of them and extrapolate what the values should look like for them. Interpolation only works for an x (y) that represents several measurements of the same variable (unlike a sample#).

Categories

Resources