2D array matrix output - python

I would like to print out Z[X][Y] values in a matrix in csv format, and I got an error. How can I print out Z[X][Y] in normal print () function?
Here is my code snippet:
Z[X][Y] = [((20-10)/99)*(X-1)+10 for X in range(1, 101) for Y in range(1, 2)]
Z[X][Y] = [((20-10)/99)*(Y-1)+10 for Y in range(1, 101) for X in range(1, 2)]
Z[X][Y] = [((60-20)/99)*(X-1)+20 for X in range(1, 101) for Y in range(100, 101)]
Z[X][Y] = [((60-20)/99)*(Y-1)+20 for Y in range(1, 101) for Y in range(100, 101)]
Here is the error message:
IndexError: list index out of range
My plan is to write a double for loop to output a 2D matrix in csv file. I am expecting a 100 rows and 100 columns matrix. Here is idea for double for loop:
for X in range (1, 101):
for Y in range (1, 101):
Z[X][1] = ((20-10)/99)*(X-1)+10
Z[1][Y] = ((20-10)/99)*(Y-1)+10
Z[X][100] = ((60-20)/99)*(X-1)+20
Z[100][Y] = ((60-20)/99)*(Y-1)+20

If you have the 2D matrix ready in Z variable you can print that matrix in CSV format using below code
#Example of 2D matrix in Z variable
#Below is the example code to create 10x10 2D matrix
Z=[[Y for y in range(1,11)] for X in range(0,10)]
# Print matrix in CSV format
for X in range(len(Z)):
print(",".join(map(str, Z[X])))

Related

scipy - interp2d - ValueError: When on a regular grid with x.size = m and y.size = n, if z.ndim == 2, then z must have shape (n, m)

When I try to run the scipy intrap2d function, I'm getting an error with a rectangular data table. I've got the initial x and y values using pandas pivot_table and am generating the z array.
ValueError: When on a regular grid with x.size = m and y.size = n, if z.ndim == 2, then z must have shape (n, m)
How can I resolve this issue?
The scipy intrep2d init function checks for the x, y and z sizes. If the table is a rectangular grid, it checks if the shape of z is equal to the shape of (len(y), len(x)). If the shape of z isn't according to the x and y lengths, then it throws the error.
if rectangular_grid:
if z.ndim == 2:
if z.shape != (len(y), len(x)):
raise ValueError("When on a regular grid with x.size = m "
"and y.size = n, if z.ndim == 2, then z "
"must have shape (n, m)")
Reference: https://gemfury.com/stream/python:scipy/0.15.0/content/interpolate/interpolate.py
This error can be resolved by correcting the swaping the position of of x and y columns
In case of using Panda pivot_table
change
df.pivot_table(values='z', index='x', columns='y')
TO
df.pivot_table(values='z', index='y', columns='x')
Alternately, you can update the z array and arrange it according to your x and y lengths.

Cannot change value of certain parts of array

Im trying to change the rows of an array with new values in a for loop, but cannot get it to work.
Problem is related to propagation of a wave packet in quantum physics.
Ive tried using the numpy.dot() function, but that doesnt work, and i tried making an easier for loop, that works.
import numpy as np
sig = 10**(-8)
x0 = 50*10**(-9)
L = 200*10**(-9)
N = 400
Nx = 1000
x = np.linspace(x0, L, N)
expsig = np.exp(-((1/2)*(x-x0)**2)/(sig**2))
expimg = np.exp(1j*(x-x0))
Phi = (1/(np.pi**(1/4)*np.sqrt(sig))*expsig*expimg)
Boxfunc = np.zeros(shape = (N, Nx))
for i in range(0, N):
SINnpi = np.sin(((i*np.pi)/L)*x)
Boxfunc[i,:] = np.sqrt(2/L)*SINnpi
Y = Boxfunc[i,:]*Phi
I expect the output to be a 400x1000 array with new calculated values from the multiplication between Phi and Boxfunc.
I just get the error message "could not broadcast input array from shape (400) into shape (1000)" when i get to the Boxfunc in the for-loop.
There is a problem with array x, it should be x = np.linspace(x0, L, Nx), then your code works.
Or you can define Boxfunc = np.zeros(shape = (Nx, N)). The problem is from the shape between x and Boxfunc.

Vecrtorized evluation of function defined by matrix over grid

I'm looking to plot the value of a function defined by a matrix over a grid of values.
Let S be an invertable 2x2 matrix and let x be a 2-dimensional vector. How can vectorize the evaluation of x#S#x over a two dimensional grid?
Here is how I currently do it. It works, but takes a beat to perform the computation since the grid is so fine.
#Initialize Matrix
S = np.zeros(shape = (2,2))
while np.linalg.matrix_rank(S)<S.shape[1]:
S = np.random.randint(-5,5+1, size = (2,2))
X,Y = [j.ravel() for j in np.meshgrid(np.linspace(-2,2,1001),np.linspace(-2,2,1001))]
Z = np.zeros_like(X)
for i,v in enumerate(zip(X,Y)):
v = np.array(v)
Z[i] = v#S#v
n = int(np.sqrt(X.size))
Z = Z.reshape(n,n)
X = X.reshape(n,n)
Y = Y.reshape(n,n)
plt.contour(X,Y,Z)
Simplest would be with stacking those X,Y into a 2-column 2D array and then using np.einsum to replace the loopy matrix-multiplications -
p = np.column_stack((X,Y)) # or np.stack((X,Y)).T
Zout = np.einsum('ij,jk,ik->i',p,S,p,optimize=True)

How to solve an equation with two variables in python

So, I want to solve an equation z with two variables (x and y having 50 values each, for example). I want to calculate something like:
import numpy as np
x = np.linspace(0, 50, 51)
y = np.linspace(100, 150, 51)
z=y-x
print z
with open("output_data.csv","w") as out_file:
for i in range(len(x)):
#print i
out_string=""
out_string+=str(x[i])
#out_string+=str(real(ky2)[i])
#print out_string
out_string += "," + str(z[i])
out_string += "\n"
out_file.write(out_string)
However I want to calculate the first x with all the y's the the second x with all; y's again and so on, until I get a set of 50 values of z, each set with 50 values. Then save in a 50 column file.
What my code is doing so fat is calculating only 50 z's for the 1st x and 1st y, 2nd x and 2nd y and so on.
Any ideas?
You need to change your code so you compute z inside the for loop:
for i in range(len(x)):
words = []
z = y-x[i]
words.append(str(x[i]))
words.append(", ".join((str(_z) for _z in z)))
outfile.write(": ".join(words))
outfile.write("\n")
With your code, you only compute z one time (outside the loop) and this does an item-wise difference of y and x as you see.
Having said this, you should change your code to not do str += .... If you are accumulating strings, use a list instead:
words = []
words.append(str(x[i]) ...

Assigning input markers to function output in python

Sorry for the seemingly elementary question. What I'm trying to implement is summarized in the following steps:
Generate input variables: x, y.
Let z = F(x,y).
Plot z's for particular combinations of x and y.
For example:
zlist = []
for _ in range(100):
x = np.random.random()*1.
y = np.random.random()*.5
if x < .5:
z = y / 2
else:
z = y * 2
zlist.append(z)
Now if I want to plot z for all the x between (0, 0.3), I presumably would need some marker on each element in zlist indicating its inputs variables. How would I attach such marker and then access it from the list when plotting?
I don't actually know anything about Numpy, so someone please comment and tell me if I'm making a fool out of myself. It seems like vanilla python behavior, though.
Rather than appending z, let's append (z,x) instead. Now zlist is a list of tuples, and you can loop through and plot by checking zlist[i][1].
zlist = []
for _ in range(100):
x = np.random.random()*1.
y = np.random.random()*.5
if x < .5:
z = y / 2
else:
z = y * 2
zlist.append((z,x))
for value in zlist:
if value[1] > 0 and value[1] < 0.3:
# Plot value[0]
# Or if you prefer list comprehensions:
# [value[0] for value in zlist if value[1] >0 and value[1] < 0.3]
# that will return a list with only the z values in zlist.
With numpy it's almost always much more efficient to perform operations on vectors and
arrays rather than on built-in Python sequence types such as lists. Here's one
way you can quickly find F(x, y) for every combination of two sets of random x
and y values without looping in Python. The result is going to be an nx-by-ny
array Z, where Z[i, j] = F(x[i], y[j]).
First of all, you can generate all of your x, y inputs as vectors:
nx = 100
ny = 200
x = np.random.random(size=nx) * 1.
y = np.random.random(size=ny) * 5.
For the result to be an nx-by-ny array, you could take these two vectors and
multiply them by ones to get two 2D nx-by-ny arrays containing the x and y
values in the rows and columns respectively. You can do this by taking advantage of numpy's
broadcasting rules:
x_arr = x[:,np.newaxis] * np.ones((nx,ny))
y_arr = y[np.newaxis,:] * np.ones((nx,ny))
The function you will apply to each x,y pair depends on the x value.
Fortunately, you can use np.where(<condition>, <do_this>, <do_that>) to apply
different operations to the values in your input depending on some condition:
Z = np.where(x_arr < 0.5, y_arr / 2., y_arr * 2.)
We can check that all the results are correct:
for i in xrange(nx):
for j in xrange(ny):
if x[i] < 0.5:
assert Z[i, j] == y[j] / 2.
else:
assert Z[i, j] == y[j] * 2
There's actually an even cleaner way to compute Z without expanding x and y into 2D arrays. Using the same broadcasting trick we used to get
x_arr and y_arr, you can pass x and y directly to np.where():
x2 = x[:,np.newaxis]
y2 = y[np.newaxis,:]
Z2 = np.where(x2 < 0.5, y2 / 2., y2 * 2.)
assert np.all(Z == Z2)

Categories

Resources