Is it possible, with Matplotlib, to print the values of each point on the graph?
For example, if I have:
x = numpy.range(0,10)
y = numpy.array([5,3,4,2,7,5,4,6,3,2])
pyplot.plot(x,y)
How can I display y values on the plot (e.g. print a 5 near the (0,5) point, print a 3 near the (1,3) point, etc.)?
You can use the annotate command to place text annotations at any x and y values you want. To place them exactly at the data points you could do this
import numpy
from matplotlib import pyplot
x = numpy.arange(10)
y = numpy.array([5,3,4,2,7,5,4,6,3,2])
fig = pyplot.figure()
ax = fig.add_subplot(111)
ax.set_ylim(0,10)
pyplot.plot(x,y)
for i,j in zip(x,y):
ax.annotate(str(j),xy=(i,j))
pyplot.show()
If you want the annotations offset a little, you could change the annotate line to something like
ax.annotate(str(j),xy=(i,j+0.5))
Use pyplot.text() (import matplotlib.pyplot as plt)
import matplotlib.pyplot as plt
x=[1,2,3]
y=[9,8,7]
plt.plot(x,y)
for a,b in zip(x, y):
plt.text(a, b, str(b))
plt.show()
Related
I need to use the streamplot function in matplotlib with coordinates x, p in the order as in the code below.
import numpy as np
import matplotlib.pyplot as plt
size = 2
x, p = np.mgrid[-size:size:100j, -size:size:100j]
x_force = p
p_force = x**3
fig = plt.figure()
ax = fig.gca()
ax.streamplot(x, p, x_force, p_force, density=[0.5, 1])
plt.show()
This produces an error: ValueError: The rows of 'x' must be equal.
Quite surprisingly, changing the order of x and p in the streamplot solves the problem.
ax.streamplot(p, x, p_force, x_force, density=[0.5, 1])
Why does this happen please? How can I make the plot with coordinates in my chosen order?
Changing the order of x and p in the meshgrid command solves the problem:
p, x = np.mgrid[-size:size:100j, -size:size:100j]
the value on y-axis does not change in my plot if I define my function outside ax.plot_wireframe().
It is the problem of my real function which longer.
import pandas
import numpy
from matplotlib import cm
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # <--- This is important for 3d plotting
a = numpy.linspace(1,10,10) # x axis
b = numpy.linspace(1,10,10) # y axis
R = a+b #model function, real function is longer
z = R
fig = plt.figure()
ax = plt.axes(projection='3d')
a,b = numpy.meshgrid(a,b)
#ax.plot_wireframe(a,b,a+b, color='b') #correct
#ax.plot_wireframe(a,b,z, color='b') #wrong
ax.plot_wireframe(a,b,R, color='b') #wrong
ax.set_title('surface');
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z');
Here is the result
Take a look at the matplotlib documentation regarding 3D wireframe plots. The x, y and z values need to be 2-dimensional. Explanations for this are given here or here. This is also the reason for the line
a,b = numpy.meshgrid(a,b)
in your code. It creates a 10x10 2D array for both 1D inputs. In the next lines you call the wireframe method with a+b for the z values. Hence, the z values are calculated in place and the result is again a 10x10 2D array. The reason why you get the "wrong" graph with the variables R or z is that they are calculated before a and b are turned into their respective 2D meshgrids. If you define R or z after the line containing numpy.meshgrid it works fine.
import pandas
import numpy
from matplotlib import cm
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # <--- This is important for 3d plotting
a = numpy.linspace(1,10,10) # x axis
b = numpy.linspace(1,10,10) # y axis
R = a+b #not working
z = R #not working
def f(x,y):
return x+y
fig = plt.figure()
ax = plt.axes(projection='3d')
a,b = numpy.meshgrid(a,b)
Z = f(a,b)#working
R = a+b #working
z = R #working
#ax.plot_wireframe(a,b,a+b, color='b') #
#ax.plot_wireframe(a,b,Z, color='b') #
ax.plot_wireframe(a,b,R, color='b') #
ax.set_title('surface');
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z');
So the short answer is: numpy.meshgrid changes your variables a and b and your are basically doing your calculations with different as and bs
I am trying to create a surface plot of a mountain in python, of which I have some xyz data. The end result should look something like that. The file is formatted as follows:
616000.0 90500.0 3096.712
616000.0 90525.0 3123.415
616000.0 90550.0 3158.902
616000.0 90575.0 3182.109
616000.0 90600.0 3192.991
616025.0 90500.0 3082.684
616025.0 90525.0 3116.597
616025.0 90550.0 3149.812
616025.0 90575.0 3177.607
616025.0 90600.0 3191.986
and so on. The first column represents the x coordinate, the middle one the y coordinate, and z the altitude that belongs to the xy coordinate.
I read in the data using pandas and then convert the columns to individual x, y, z NumPy 1D arrays. So far I managed to create a simple 3D scatter plot with a for loop iterating over each index of each 1D array, but that takes ages and makes the appearance of being quite inefficient.
I've tried to work with scipy.interpolate.griddata and plt.plot_surface, but for z data I always get the error that data should be in a 2D array, but I cannot figure out why or how it should be 2D data. I assume that given I have xyz data, there should be a way to simply create a surface from it. Is there a simple way?
Using functions plot_trisurf and scatter from matplotlib, given X Y Z data can be plotted similar to given plot.
import sys
import csv
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
# Read CSV
csvFileName = sys.argv[1]
csvData = []
with open(csvFileName, 'r') as csvFile:
csvReader = csv.reader(csvFile, delimiter=' ')
for csvRow in csvReader:
csvData.append(csvRow)
# Get X, Y, Z
csvData = np.array(csvData)
csvData = csvData.astype(np.float)
X, Y, Z = csvData[:,0], csvData[:,1], csvData[:,2]
# Plot X,Y,Z
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(X, Y, Z, color='white', edgecolors='grey', alpha=0.5)
ax.scatter(X, Y, Z, c='red')
plt.show()
Here,
file containing X Y Z data provided as argument to above script
in plot_trisurf, parameters used to control appearance. e.g. alpha used to control opacity of surface
in scatter, c parameter specifies color of points plotted on surface
For given data file, following plot is generated
Note: Here, the terrain is formed by triangulation of given set of 3D points. Hence, contours along surface in plot are not aligned to X- and Y- axes
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
import pandas as pd
df = pd.read_csv("/content/1.csv")
X = df.iloc[:, 0]
Y = df.iloc[:, 1]
Z = df.iloc[:, 2]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(X, Y, Z, color='white', edgecolors='grey', alpha=0.5)
ax.scatter(X, Y, Z, c='red')
plt.show()
My output image below - I had a lot of data points:
enter image description here
There is an easier way to achieve your goal without using pandas.
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
x, y = np.mgrid[-2 : 2 : 20j, -2 : 2 : 20j]
z = 50 * np.sin(x + y) # test data
output = plt.subplot(111, projection = '3d') # 3d projection
output.plot_surface(x, y, z, rstride = 2, cstride = 1, cmap = plt.cm.Blues_r)
output.set_xlabel('x') # axis label
output.set_xlabel('y')
output.set_xlabel('z')
plt.show()
I am trying to plot a graph using matplotlib.pyplot.
import matplotlib.pyplot as plt
import numpy as np
x = [i for i in range (1,201)]
y = np.loadtxt('final_fscore.txt', dtype=np.float128)
plt.plot(x, y, lw=2)
plt.show()
It looks something like this:
I want to mark the first value of x where y has reached the highest ( which is already known, say for x= 23, y= y[23]), like this figure shown below:
I have been searching this for some time now, with little success. I have tried adding a straight line for now, which is not behaving the desired way:
import matplotlib.pyplot as plt
import numpy as np
x = [i for i in range (1,201)]
y = np.loadtxt('final_fscore.txt', dtype=np.float128)
plt.plot(x, y, lw=2)
plt.plot([23,y[23]], [23,0])
plt.show()
Resulting graph:
Note: I want to make the figure like in the second graph.
It's not clear what y[23] would do here. You would need to find out the maximum value and the index at which this occurs (np.argmax). You may then use this to plot a 3 point line with those coordinates.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(9)
x = np.arange(200)
y = np.cumsum(np.random.randn(200))
plt.plot(x, y, lw=2)
amax = np.argmax(y)
xlim,ylim = plt.xlim(), plt.ylim()
plt.plot([x[amax], x[amax], xlim[0]], [xlim[0], y[amax], y[amax]],
linestyle="--")
plt.xlim(xlim)
plt.ylim(ylim)
plt.show()
I don't know how to tell matplotlib to use different axis in one peculiar subplot of an array subplot:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
def plotter():
y=np.random.rand(10)
y1 = np.random.rand(10)*100
x = np.arange(len(y))
f, axarr = plt.subplots(2,2,sharex=True)
axarr[0][0].errorbar(x,y,)
axarr[0][0].errorbar(x,y1)
axarr[1][1].twinx()
axarr[1][1].errorbar(x,y)
axarr[1][1].errorbar(x,y1)
plt.show()
plotter()
This gives:
The issue is that my one data set is greater by a factor of hundred, so plotting them on the same y axis is useless. What I want to have for the lower right panel (and only for this panel) is one y axis that ranges from (0,10) on the right side of the plot and one that ranges from (0,100) on the other side. The blue line should be represented by the right (0,10) y axis, while the blue line should be represented by the left (0,100) y axis
One way of doing this is:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
def plotter():
y=np.random.rand(10)
y1 = np.random.rand(10)*100
x = np.arange(len(y))
f, axarr = plt.subplots(2,2,sharex=True)
axarr[0][0].errorbar(x,y,)
axarr[0][0].errorbar(x,y1)
axarr[1][1].errorbar(x,y)
ax2 = axarr[1][1].twinx()
ax2.plot(x,y1, 'r')
#ax2.tick_params('y', colors='r')
plt.show()
plotter()
Which gives this: