Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
i want to plot a regression line by using a (x,y) point.
I did something like this
import numpy as np
from numpy.polynomial.polynomial import polyfit
import matplotlib.pyplot as plt
import scipy
# Sample data
x = np.array([4.2])
y = np.array([2.8])
plt.plot(x, y, 'o')
m, b = np.polyfit(x, y, 1)
print(m)
print(b)
plt.plot(x, m*x + b)
plt.show()
However, it only plot the point not line.Can you please suggest how to plot the line.Thanks in advance.
Your data contains only one point. In general, we want to display the fitted curve over the entire x-domain. (Even if here the regression is linear and only requires 2 points).
# Display the regression curve
x_dom = np.linspace(0, 5, 200)
y_reg = m * x_dom + b
plt.plot(x_dom, y_reg, c="royalblue", label="Regression curve")
plt.plot(x, y, 'o', c="orange", label="Data")
plt.legend()
plt.show()
Note that fitting one point does not make sense. An infinity number of straight lines pass through that point. If you know a second point (such as the origin), the coefficients of the line that passes through these two points can be obtained analytically.
You code works fine, I just added the (0,0) point:
import numpy as np
from numpy.polynomial.polynomial import polyfit
import matplotlib.pyplot as plt
import scipy
# Sample data
x = np.array([0, 4.2])
y = np.array([0, 2.8])
plt.plot(x, y, 'o')
m, b = np.polyfit(x, y, 1)
print(m)
print(b)
plt.plot(x, m*x + b)
output:
Related
I have two data sets index_list and frequency_list which I plot in a loglog plot by plt.loglog(index_list, freq_list). Now I'm trying to fit a power law a*x^(-b) with linear regression. I expect the curve to follow the initial curve closely but the following code seems to output a similar curve but mirrored on the y-axis.
I suspect I am using curve_fit badly.
why is this curve mirrored on the x-axis and how I can get it to properly fit my inital curve?
Using this data
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
f = open ("input.txt", "r")
index_list = []
freq_list = []
index = 0
for line in f:
split_line = line.split()
freq_list.append(int(split_line[1]))
index_list.append(index)
index += 1
plt.loglog(index_list, freq_list)
def power_law(x, a, b):
return a * np.power(x, -b)
popt, pcov = curve_fit(power_law, index_list, freq_list)
plt.plot(index_list, power_law(freq_list, *popt))
plt.show()
The code below made the following changes:
For the scipy functions to work, it is best that both index_list and freq_list are numpy arrays, not Python lists. Also, for the power not to overflow too rapidly, these arrays should be of float type (not of int).
As 0 to a negative power causes a divide-by-zero problem, it makes sense to start the index_list with 1.
Due to the powers, also for floats an overflow can be generated. Therefore, it makes sense to add bounds to curve_fit. Especially b should be limited not to cross about 50 (the highest value is about power(100000, b) giving an overflow when be.g. is100). Also setting initial values helps to direct the fitting process (p0=...).
Drawing a plot with index_list as x and power_law(freq_list, ...) as y would generate a very weird curve. It is necessary that the same x is used for the plot and for the function.
Note that calling plt.loglog() changes both axes of the plot to logarithmic. All subsequent plots on the same axes will continue to use the logarithmic scale.
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import pandas as pd
import numpy as np
def power_law(x, a, b):
return a * np.power(x, -b)
df = pd.read_csv("https://norvig.com/google-books-common-words.txt", delim_whitespace=True, header=None)
index_list = df.index.to_numpy(dtype=float) + 1
freq_list = df[1].to_numpy(dtype=float)
plt.loglog(index_list, freq_list, label='given data')
popt, pcov = curve_fit(power_law, index_list, freq_list, p0=[1, 1], bounds=[[1e-3, 1e-3], [1e20, 50]])
plt.plot(index_list, power_law(index_list, *popt), label='power law')
plt.legend()
plt.show()
I am writting a very simple script, one that plot a sin using jupyter notebook (python 3). when I put:
import numpy
import matplotlib.pyplot as plt
x=np.arange(0.0,5*np.pi,0.001)
y = np.sin(x)
plt.plot(x,y)
The plot is fine.
However if :
import numpy
import matplotlib.pyplot as plt
x=np.arange(0.0,5*np.pi,0.001)
np.random.shuffle(x)
y = np.sin(x)
plt.plot(x,y)
the image is
I don't understand why shuffling the x BEFORE I ran sin does it.
thank you
Let's first simplify things a bit. We plot 4 points and annote them with the order in which they are plotted.
import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
x=np.arange(4)
y = np.sin(x)
plt.plot(x,y, marker="o")
for i, (xi,yi) in enumerate(zip(x,y)):
plt.annotate(str(i), xy=(xi,yi), xytext=(0,4),
textcoords="offset points", ha="center")
plt.show()
No if we shuffle x and plot the same graph,
x=np.arange(4)
np.random.shuffle(x)
y = np.sin(x)
we see that positions of the points are still are the same, but while e.g. previously the first point was the one at (0,0), it's now the third one appearing there. Due to this randomized order, the connecting lines go zickzack.
Now if you use enough points, all those lines will add up to look like a complete surface, which is what you get in your image.
I created a heatmap from a scatterplot of csv values using the code i found from a different stackoverflow thread here Generate a heatmap in MatPlotLib using a scatter data set
This works but I'd like to edit the colours/smooth between bins etc. I've read this https://matplotlib.org/examples/color/colormaps_reference.html ...but my level of n00b is preventing swift progress. Does my current code seem ameanable to easy manipulation for interpolation between bins (smoothing) or at least a colour change, or do I need to create my heatmap in a different way to gain more control? (the heatmap will represent how often a space is used in time, based on x y values of a tracked item)
Thanks , any help much appreciated.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import csv
with open('myfile.csv') as csvfile:
readCSV = csv.reader(csvfile, delimiter=',')
y = []
x = []
for row in readCSV:
x.append(float(row [0]))
y.append(float(row [1]))
print (x, y)
heatmap, xedges, yedges = np.histogram2d(x,y,bins=20)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
plt.clf()
plt.imshow(heatmap.T, extent=extent)
plt.show()
I have drawn the following figure. Is it possible to make the figure with length 2 unit & height 1 unit? Also is it possible to change plt.xlabel('time (s)') to plt.xlabel('$\alpha \rightarrow$')?
import matplotlib.pyplot as plt
import numpy as np
t=[0,1,2]
s=[0.05,0.1,0.2]
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
#plt.title('About as simple as it gets, folks')
plt.grid(True)
plt.savefig("test.png")
plt.show()
You answered your own question about the figure size.
For the second question you just need a raw string, e.g.: plt.xlabel(r'$\alpha \rightarrow$')
To make the alpha bold -- as requested in a comment -- it's a little more involved. Per https://tex.stackexchange.com/a/99286 you'd do:
import matplotlib
matplotlib.rc('text', usetex=True)
matplotlib.rcParams['text.latex.preamble']=[r"\usepackage{amsbsy}"]
t=[0,1,2]
s=[0.05,0.1,0.2]
plt.plot(t, s)
plt.ylabel('voltage (mV)')
plt.xlabel(r'$\pmb{\alpha}$ \rightarrow$')
plt.show()
With histograms, there's a simple built-in option histtype='step'. How do I make a bar plot in the same style?
[adding answer after reading the comments]
Set the optional keyword to be fill=False for bar plots:
import matplotlib.pyplot as plt
plt.bar(bins[:5], counts[:5], fill=False, width=60) # <- this is the line
plt.title("Number of nodes with output at timestep")
plt.xlabel("Node count")
plt.ylabel("Timestep (s)")
will give:
Or use plt.plot with the keyword ls='steps' :
plt.plot(bins[-100:], counts[-100:], ls='steps')
plt.title("Number of nodes with output at timestep")
plt.xlabel("Node count")
plt.ylabel("Timestep (s)")
Although OP linked to a post that answered a slightly different question relating to histogram step plots, here is a solution for anyone passing through here who is specifically trying to turn off the face color in pyplot.bar bar plots:
import matplotlib.pyplot as plt
import numpy as np
# create x coords for the bar plot
x = np.linspace(1, 10, 10)
# cook up some random bar heights -- exact results may vary :-P
y = np.random.randn(10)
z = np.random.randn(10) * 2
# plot bars with face color off
plt.bar(x-0.2, y, width=0.4, edgecolor='purple', color='None')
plt.bar(x+0.2, z, width=0.4, edgecolor='darkorange', color='None')
plt.show()
Note that bar edges have settable matplotlib.lines.Line2D attributes, such as linewidth, linestyle, alpha, et cetera:
plt.bar(x-0.2, y, width=0.4, edgecolor='purple', color='None',
linewidth=0.75, linestyle='--')
plt.bar(x+0.2, z, width=0.4, edgecolor='darkorange', color='None',
linewidth=1.5, linestyle='-.')
plt.show()
I saw you found an answer on this other topic, nonetheless I have the feeling matplotlib.pyplot.step does the job too and is more direct (see here).
Edit: as requested, some sample code to illustrate usage of plt.step
import matplotlib.pyplot as plt
plt.step(list(range(10)),list(range(5))+list(range(5)))