y = dsleep["TotalTimeInBed"]
x = dsleep["TotalMinutesAsleep"]
plt.scatter(x,y,color = "red")
plt.plot([0,0],[961,961])
plt.title("relation between total minutes asleep and total time in bed")
plt.ylabel("total time in bed")
plt.xlabel("total minutes asleep")
I tried this code but it ignored the line and output was simply a scatterplot. How should I plot a straight line of slope 45 degree over my scatter plot for comparing my data points
Given your task, I presume you want the unity line. Then you should code plt.plot([0, 961], [0, 961])
Your line, as it is now, has zero length
What you are actually searching for is a trendline on your scatter plot. You can achieve that with np.polyfit()
import numpy as np
x = np.arange(20)
y = [num + random.choice(range(-5, 5)) for num in x]
plt.scatter(x, y)
z = np.poly1d(np.polyfit(x, y, deg=1)) # deg -> 1 - linear, 2 - quadratic ...
plt.plot(x,z(x),"r--")
plt.show()
Related
I'm having a curve as follows:
The curve is generated with the following code:
import matplotlib.pyplot as plt
import numpy as np
# normalize array
def min_max_scale_array(arr):
arr = np.array(arr)
return (arr - arr.min())/(arr.max()-arr.min())
x = np.linspace(-50,48,100)
y = x**2 + 2*x + 2
x = min_max_scale_array(x)
y = min_max_scale_array(y)
fig, ax = plt.subplots()
ax.plot(x, y)
How can I generate a new curve by moving only the bottom left (or right) and keeping both ends the same like this? Thank you!
Edit: any curve generating algorithm is appreciated, as long as it works!
One way of doing so is defining x,y as before, but applying a shift. The dotted line shows if you just shift it. But now at the top most y we don't want to shift it, so we'd like to weight the shifted version on the bottom (y=0) by 1 but on the top (y=1) by 0 such that we get a gradual interpolation. We can do this by multiplying the shift by (1-y):
a = 0.25 # how far to shift left
plt.plot(x, y, 'k')
plt.plot(x-a, y, 'k:')
plt.plot(x-a*(1-y), y, 'r')
plt.show()
Easiest solution: apply a sublinear transformation to x - a quadratic function will work.
x = x**2 # works because x is scaled to 0-1
ax.plot(x, y)
UPD: as requested, a scaling factor would look something like:
scaling_factor = 0.7
x = scaling_factor*(x**2) + (1-scaling_factor)*x
I have a code:
import matplotlib.pyplot as plt
import numpy as np
# create 1000 equally spaced points between -10 and 10
x = np.linspace(-10, 10, 1000)
# calculate the y value for each element of the x vector
y = 2*x**2 - 3*x + 5
# draw a tangent line to parabola at x = -1
a = -7*x + 3
# draw a normal line to parabola at x = -1
b = 1/7*x + 71/7
fig, ax = plt.subplots()
ax.plot(x, y)
ax.plot(x, a)
ax.plot(x, b)
With this code I am trying to plot a parabola, a tangent line to parabola at x = -1 and a line that is normal to the tangent line at x = -1. The parabola and the the tangent line seemingly are plotting correctly, but the normal line always plots parallel to the x axis. What am I doing wrong? First picture(top) is what i get with matplotlib and the second picture is what it should look like (graphing calc.)
There are two things going wrong here. The first was answered Jody in his comment, the aspect ratio is off. The second problem is the fact that the y-axis value of the parabola goes all the way up to 250. This essentially "flattens" the look of the normal line. You can fix this by cutting of the y-axis using ax.set_ylim(). Try the following:
ax.set_aspect(1)
ax.set_ylim([-5, 20])
This will produce an image with that represents the lines correctly (i.e. you can see the right angles) but the effective aspect ratio of the output figure is not square or of the desired aspect ratio you might want. You can adjust this further by changing the linspace, for instance to x=np.linspace(-20,20,1000).
I am new to Python code and I need to graph my experiment data for my lab portfolio however I can't seem to log the y-axis and offset the x-axis or even know where to start for the gradient.
I have tried np.log in various different ways and each time I get an error, for the offset (which 26408) I tried just subtracting that number from x, I have tried creating an array and subtracting that and again I end up with various errors.
import matplotlib.pyplot as plt
%matplotlib inline
f = open("Large C 100ohms","r")
lines = f.readlines()[1:]
x = [line.split()[0] for line in lines]
y = [line.split()[1] for line in lines]
x_1 = np.array(x)
#print(x_1)
y_1 = np.array(y)
#print(y_1)
#offset x axis
#log y axis
plt.plot(x, y,'bo', linestyle='-')
plt.gca().invert_yaxis()
plt.xlabel('Time(ms)')
plt.ylabel('Voltage(V)')
plt.title('100 ohms')
#gradient
plt.show()
f.close()`
splitting lines yields strings. convert them to numbers: float(line.split()[0]) (or int() if you have integers)
plt.yscale('log')
x limits should be adjusted automatically. if you want to transform the data you can do
x_1 = x_1 + offset
or you can fiddle with
plt.xlim(low, high)
An equation which is represent as below
sin(x)*sin(y)*sin(z)+cos(x)*sin(y)*cos(z)=0
I know the code to plot function for z=f(x,y) using matplotlib but to plot above function I don’t know the code, but I tried MATLAB MuPad code which is as follows
Plot(sin(x)*sin(y)*sin(z)+cos(x)*sin(y)*cos(z),#3d)
This will be much easier if you can isolate z. Your equation is the same as sin(z)/cos(z) = -cos(x)*sin(y)/(sin(x)*sin(y)) so z = atan(-cos(x)*sin(y)/(sin(x)*sin(y))).
Please don't mistake me, but I think your given equation to plot can be reduced to a simple 2D plot.
sin(x)*sin(y)*sin(z)+cos(x)*sin(y)*cos(z) = 0
sin(y)[sin(x)*sin(z)+cos(x)*cos(z)] = 0
sin(y)*cos(x-z) = 0
Hence sin(y) = 0 or cos(x-z)=0
Hence y = n*pi (1) or x-z=(2*n + 1)pi/2
Implies, x = z + (2*n + 1)pi/2 (2)
For (1), it will be a straight line (the plot of y vs n) and in second case, you will get parallel lines which cuts x-axis at (2*n + 1)pi/2 and distance between two parallel lines would be pi. (Assuming you keep n constant).
Assuming, your y can't be zero, you could simplify the plot to a 2D plot with just x and z.
And answering your original question, you need to use mplot3d to plot 3D plots. But as with any graphing tool, you need values or points of x, y, z. (You can compute the possible points by programming). Then you feed those points to the plot, like below.
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.axes(projection="3d")
xs = [] # X values
ys = [] # Y values
zs = [] # Z values
ax.plot3D(xs, ys, zs)
plt.show()
I create a graph of a logarithmic spiral in the form of a spring. I'm using the below parametric equations:
x=a*exp(b*th)*cos(th)
y=a*exp(b*th)*sin(th)
Here is my code:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['legend.fontsize'] = 10
fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')
a=0.6
b=0.2
th=np.linspace(0, 25, 1000)
x=a*np.exp(b*th)*np.cos(th)
y=a*np.exp(b*th)*np.sin(th)
z = np.linspace(0, 2, len(th))
ax.plot(x, y, z)
ax.plot(x, y, zdir='z', zs=0)
ax.plot(x, z, zdir='y', zs=100)
ax.set_xlim([-100, 100])
ax.set_ylim([-100, 100])
ax.set_zlim([-0, 2.5])
plt.show()
This gives me the following output:
Can I get the length of the entire spiral? Is it possible to mark the position of a point on the graph, which lies in the distance (for example, 5), starting from the beginning of the graph in point (x,y)=(0,0), and pull out these coordinates? I will be grateful for any tips.
Pythagoras works as well in 3 dimensions. Any line segment si has a length of
si = sqrt(xi**2+yi**2+zi**2)
Hence,
a=0.6
b=0.2
th=np.linspace(0, 25, 1000)
x=a*np.exp(b*th)*np.cos(th)
y=a*np.exp(b*th)*np.sin(th)
z = np.linspace(0, 2, len(th))
diffs = np.sqrt(np.diff(x)**2+np.diff(y)**2+np.diff(z)**2)
length = diffs.sum()
print length # prints 451.011712939
the length of the line is 451.
Note that the extention of the line in z direction is much smaller than in x and y, so we might as well leave out z completely, the error when doing so is 0.025 or 0.006%.
The other aim is to find the point on the line where the line is some length l=5 long. Of course since we work with numerical data, we do not find the point where it is exactly 5 units long, but e.g. rather that point where the length is smaller than 5 but closest to it. We can calculate the index at which point that happens,
l = 5 # length to find coordinate of
cumlenth = np.cumsum(diffs)
s = np.abs(np.diff(np.sign(cumlenth-l))).astype(bool)
c = np.argwhere(s)[0][0]
and then find that index in the original arrays.
print c # index of coordinate, here 192
print x[c], y[c], z[c] # 0.144750230412 -1.56183108038 0.384384384384
We might then label that point with a scatter,
ax.scatter([x[c]], [y[c]], [z[c]], color="crimson")