How to solve an equation with two variables in python - 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]) ...

Related

How to make a condition to terminate appending?

I am writing a code to plot several projectile trajectories of various theta values in Python.
theta = np.arange(np.pi/6, np.pi/3)
t = np.linspace(0,2,num=100)
while y0>=0:
for i in theta:
x = []
y = []
for k in t:
x0= v_0*np.cos(i)*k
y0= v_0*np.sin(i)*k - 1/2*g*(k**2)
x.append(x0)
x.append(y0)
After forming the arrays and putting in the necessary conditions for projectile, I have used a while loop to put the terminating instruction in the program. I think, I am missing a crucial point. Thanks!
I think you want your terminating condition inside your inner-most loop. See below, where I also defined a couple of missing constants (v_0, g) and fixed one x to y. also printing the results
theta = np.arange(np.pi/6, np.pi/3)
t = np.linspace(0,2,num=100)
v_0 = 1
g=10
for i in theta:
x = []
y = []
for k in t:
x0= v_0*np.cos(i)*k
y0= v_0*np.sin(i)*k - 1/2*g*(k**2)
x.append(x0)
y.append(y0)
if y0 < 0: # the main change here. Stop looping when y_0 below zero
break
print(f'theta:{i}')
print(f'x:{x}')
print(f'y:{y}')
produces
theta:0.5235987755982988
x:[0.0, 0.017495462702715934, 0.03499092540543187, 0.052486388108147805, 0.06998185081086374, 0.08747731351357968]
y:[0.0, 0.008060401999795939, 0.012039587797163551, 0.011937557392102841, 0.007754310784613805, -0.0005101520253035577]
Plotting it (y vs x), looks reasonable
It is also worth noting that your definition of theta = np.arange(np.pi/6, np.pi/3) looks rather strange, what are you trying to achieve here?

Nested for loop to multiply two lists by two variables python 3

I'm importing a CSV file into Python, then performing least squares regression with the x and y values. So far my program:
opens CSV file and delimits at commas
creates two lists consisting of X and Y (x_list and y_list, respectively)
calculates the average of all the values of X, and does the same for all the
values of Y (x_avg and y_avg, respectively)
I'm having trouble finding the numerator of the slope:
sum((Xi - X avg) * (Yi - Y avg))
I'm using a nested for loop but am getting an incorrect result back for my m_num (slope numerator).
def compute_numerator(x_list, y_list, x_avg, y_avg):
m_num = 0
xi = []
yi = []
multiples = []
xi = [(x - x_avg) for x in x_list]
yi = [(y - y_avg) for y in y_list]
for x in xi:
for y in yi:
multiples = [x * y]
m_num = sum(multiples)
print(m_num)
return m_num
I need m_num to return the sum of all the values of (X - the average of X) * (Y - the average of Y)
Any suggestions or critiques welcome! Trying to learn and also pick up good programming habits. Thanks for your time!
If you want each (x, y) value in x_list,y_list paired up with each other, this would work:
sum((x-x_avg)*(y-y_avg) for x, y in zip(x_list, y_list))
Your problem is that you're not pairing them, and instead having each x value sum with all y values, like so:
sum((x-x_avg)*(y-y_avg) for x, y in x_list for y in y_list)

Combining different elements of array in Numpy while doing vector operations

I have a function f which I am using to evolve a Numpy array z repeatedly. Thus my code looks like this:
for t in range(100):
z = f(z)
However, now I want to combine elements of array while evolving. For example, in simple Python, I would like to do something like this:
N = len(z)
for t in range(100):
for i in range(len(z)):
z_new[i] = f(z[i]) + z[(i-1)%N] + z[(i+1)%N]
z = z_new
How can achieve the same thing in Numpy vector operations so that I wouldn't have to compromise with the great speed that Numpy gives me?
Thanks in advance
You can roll the data back and forth to achieve the same result.
Z = f(z)
Z = np.roll(Z, 1) + z
Z = np.roll(Z, -2) + z
z = np.roll(Z, 1)
I had also first thought about slicing but went with np.roll when I found it.
Prompted by #hpaulj's comment I came up with a slice solution:
q = np.array([1,2,3,4,5])
Q = f(q)
# operate on the middle
Q[1:] += q[:-1]
Q[:-1] += q[1:]
# operate on the ends
Q[0] += q[-1]
Q[-1] += q[0]
q = Q.copy()

Defining an ellipse around data points

I have a question/idea that I am not sure how to do.
I have a scatter plot of X vs. Y
I can draw a rectangle and then pick all the points within in.
Ideally I want to define a ellipse as it better captures the shape and exclude all the points that are outside it.
How does one do this? is it even possible? I drew the plot using matplotlib.
I used Linear Regression (LR) to fit the points but thats not really what I am looking for.
I want to define APPROXIMATELY a ellipse to cover as many points as possible within it and then exclude points outside it. How can I define an equation/code to pick the ones inside ?
If you have the data structure that is represented in the graph, you can do this with a function and a list comprehension.
If you have the data in a list like this:
# Made up data
lst = [
# First element is X, second is Y.
(0,0),
(92,20),
(10,0),
(13,40),
(27,31),
(.5,.5),
]
def shape_bounds(x):
"""
Function that returns lower and upper bounds for y based on x
Using a circle as an example here.
"""
r = 4
# A circle is x**2 + y**2 = r**2, r = radius
if -r <= x <= r:
y = sqrt(r**2-x**2)
return -y, y
else:
return 1, -1 # Remember, returns lower, upper.
# This will fail any lower < x < upper test.
def in_shape(elt):
"""
Unpacks a pair and tests if y is inside the shape bounds given by x
"""
x, y = elt
lower_bound, upper_bound = shape_bounds(x)
if lower_bound < y < upper_bound:
return True
else:
return False
# Demo walkthrough
for elt in lst:
x, y = elt
print x, y
lower_bound, upper_bound = shape_bounds(x)
if lower_bound < y < upper_bound:
print "X: {0}, Y: {1} is in the circle".format(x, y)
# New list of only points inside the shape
new_lst = [x for x in lst if in_shape(x)]
As for an ellipse, try changing the shape equation based on this

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