Right now I have a grid in my plots using the option
from matplotlib import pyplot as plt
plt.grid(True)
Because of the nature of my plot, the lines of the grid are at every 500 units in x and every 5 units in y. Is there a way where I can increment the number of horizontal lines (i.e. increment to a line per y unit)?
You can do this with which='minor', but you need to turn on minor ticks first. For example:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0,10,100)
y = x**2
plt.plot(x,y)
ax = plt.gca()
minor_ticks = np.arange(0,100,5)
ax.set_yticks(minor_ticks, minor=True)
ax.yaxis.grid(which='minor')
plt.show()
Related
I am trying to draw a curve without a line (skeleton). I want the axis and grid lines only.
Here is the code.
++++++++++
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams["figure.figsize"] = [10.00, 7.00]
plt.rcParams["figure.autolayout"] = True
x = [1.6,2,2.5,3.2,4,5,6.3,8,10,13,16,20,25,32,40,50,63,80,100,130,160,200,250,320,400,500,630,800,1000]
y = range(1,10000,350)#[1,10,100,1000,10000]
# Display grid
plt.grid(True, which="both")
default_x_ticks = range(len(x))
plt.plot(default_x_ticks, y)
plt.yscale('log')
plt.xticks(default_x_ticks, x, rotation=90)
plt.show()
+++++++
Kindly help draw without the curve.
By adding
print(plt.xlim())
print(plt.ylim())
to your code you get the exact axis limits.
These can be used in a second run to create the plot without actually plotting anything:
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams["figure.figsize"] = [10.00, 7.00]
plt.rcParams["figure.autolayout"] = True
x = [1.6,2,2.5,3.2,4,5,6.3,8,10,13,16,20,25,32,40,50,63,80,100,130,160,200,250,320,400,500,630,800,1000]
y = range(1,10000,350)#[1,10,100,1000,10000]
# Display grid
plt.grid(True, which="both")
default_x_ticks = range(len(x))
# plt.plot(default_x_ticks, y)
plt.yscale('log')
plt.xticks(default_x_ticks, x, rotation=90)
plt.xlim(-1.4, 29.4)
plt.ylim(0.6315917965717447, 15517.934294269562)
plt.show()
In my simple example below, how to make x-axis tick values to appear between grids?
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
x = range(10)
y = np.random.random(10)
plt.plot(x,y)
plt.xticks(x)
plt.grid(True)
plt.show()
The following make ticks to be where I want but the grid lines also moves.
np.random.seed(1)
x = range(10)
y = np.random.random(10)
plt.plot(x,y)
plt.xticks(x)
plt.grid(True)
plt.xticks(np.arange(10)+0.5, x)
plt.show()
I would like the result to be:
You can set the minor ticks so that only 1 minor tick appears inbetween your major ticks. This is done using matplotlib.ticker.AutoMinorLocator. Then, set the gridlines to only appear at the minor ticks. You also need to shift your xtick positions by 0.5:
from matplotlib.ticker import AutoMinorLocator
np.random.seed(10)
x = range(10)
y = np.random.random(10)
plt.plot(x,y)
plt.xticks(np.arange(0.5,10.5,1), x)
plt.xlim(0,9.5)
plt.ylim(0,1)
minor_locator = AutoMinorLocator(2)
plt.gca().xaxis.set_minor_locator(minor_locator)
plt.grid(which='minor')
plt.show()
Edit: I'm having trouble getting two AutoMinorLocators to work on the same axis. When trying to add in another one for the y axis, the minor ticks get messed up. A work around I have found is to manually set the locations of the minor ticks using a matplotlib.ticker.FixedLocator and passing in the locations of the minor ticks.
from matplotlib.ticker import AutoMinorLocator
from matplotlib.ticker import FixedLocator
np.random.seed(10)
x = range(10)
y = np.random.random(10)
plt.plot(x,y)
plt.xticks(np.arange(0.5,10.5,1), x)
plt.yticks([0.05,0.15,0.25,0.35,0.45,0.55,0.65,0.75,0.85,0.95,1.05], [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])
plt.xlim(0,9.5)
plt.ylim(0,1.05)
minor_locator1 = AutoMinorLocator(2)
minor_locator2 = FixedLocator([0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])
plt.gca().xaxis.set_minor_locator(minor_locator1)
plt.gca().yaxis.set_minor_locator(minor_locator2)
plt.grid(which='minor')
plt.show()
If you use plt.subplots for figure creation, you get an axes object, too:
f, ax = plt.subplots(1)
This one has a better Interface for adjusting grid/ticks. Then you can give explicitly x-values for your data shifted 0.5 to the left. The same do with the minor ticks and let the grid be shown at the minor ticks:
f, ax = plt.subplots(1)
ax.set_xticks(range(10))
x_values = np.arange(10) - .5
ax.plot(x_values, np.random.random(10))
ax.set_xticks(x_values, minor=True)
ax.grid(which='minor')
I have some code to plot a grid, with the data in each cell being distinct and having a very specific position. The easiest way I found to do this was to create the grid with gridspec and use it to precisely position my subplots, however I'm having a problem where the overall grid is labelled from 0 to 1 along each axis. This happens every time, even when the dimensions of the grid are changed. Obviously these numbers have no relevance to my data, and as what I am aiming to display is qualitative rather than quantitative I would like to remove all labels from this plot entirely.
Here is a link to an image with an example of my problem
And here is the MWE that I used to create that image:
import numpy as np
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
# mock-up of data being used
x = 6
y = 7
table = np.zeros((x, y))
# plotting
fig = plt.figure(1)
gs = gridspec.GridSpec(x, y, wspace=0, hspace=0)
plt.title('Example Plot')
for (j, k), img in np.ndenumerate(table):
ax = fig.add_subplot(gs[x - j - 1, k])
ax.set_xticklabels('')
ax.set_yticklabels('')
plt.show()
I have not been able to find note of anything like this problem, so any help would be greatly appreciated.
If you just want to draw a grid over the plot, use this code:
import numpy as np
import matplotlib.pyplot as plt
# mock-up of data being used
x = 6
y = 7
table = np.zeros((x, y))
# plotting
fig = plt.figure(1)
plt.title('Example Plot')
plt.gca().xaxis.grid(True, color='darkgrey', linestyle='-')
plt.gca().yaxis.grid(True, color='darkgrey', linestyle='-')
plt.show()
Another variant is used gridspec:
...
# hide ticks of main axes
ax0 = plt.gca()
ax0.get_xaxis().set_ticks([])
ax0.get_yaxis().set_ticks([])
gs = gridspec.GridSpec(x, y, wspace=0, hspace=0)
plt.title('Example Plot')
for (j, k), img in np.ndenumerate(table):
ax = fig.add_subplot(gs[x - j - 1, k])
# hide ticks of gribspec axes
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
I have the coordinates of map of india. x-axis range is 65 to 100 and y-axis range is 0-100. I have generated grid in this range. I want to get the coordinates of the grid plot. how can i get that?
#!usr/bin/env python
import matplotlib.pyplot as plt
import numpy as np
f = np.loadtxt('New_Coordinate.txt')
fig = plt.figure()
ax = fig.gca()
ax.set_xticks(np.arange(65,100,1))
ax.set_yticks(np.arange(0,100,1))
plt.plot(f[:,:1],f[:,1:],'ro')
plt.grid()
plt.show()
The grid points are created at the locations of the tick marks on both axes.
You can then use itertools.product to get all of the pairs of those points which would be where the grid lines intersect.
import itertools
xticks = ax.get_xticks()
yticks = ax.get_yticks()
gridpoints = list( itertools.product(xticks, yticks) )
I have a very simple question. I need to have a second x-axis on my plot and I want that this axis has a certain number of tics that correspond to certain position of the first axis.
Let's try with an example. Here I am plotting the dark matter mass as a function of the expansion factor, defined as 1/(1+z), that ranges from 0 to 1.
semilogy(1/(1+z),mass_acc_massive,'-',label='DM')
xlim(0,1)
ylim(1e8,5e12)
I would like to have another x-axis, on the top of my plot, showing the corresponding z for some values of the expansion factor. Is that possible? If yes, how can I have xtics ax
I'm taking a cue from the comments in #Dhara's answer, it sounds like you want to set a list of new_tick_locations by a function from the old x-axis to the new x-axis. The tick_function below takes in a numpy array of points, maps them to a new value and formats them:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()
X = np.linspace(0,1,1000)
Y = np.cos(X*20)
ax1.plot(X,Y)
ax1.set_xlabel(r"Original x-axis: $X$")
new_tick_locations = np.array([.2, .5, .9])
def tick_function(X):
V = 1/(1+X)
return ["%.3f" % z for z in V]
ax2.set_xlim(ax1.get_xlim())
ax2.set_xticks(new_tick_locations)
ax2.set_xticklabels(tick_function(new_tick_locations))
ax2.set_xlabel(r"Modified x-axis: $1/(1+X)$")
plt.show()
You can use twiny to create 2 x-axis scales. For Example:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()
a = np.cos(2*np.pi*np.linspace(0, 1, 60.))
ax1.plot(range(60), a)
ax2.plot(range(100), np.ones(100)) # Create a dummy plot
ax2.cla()
plt.show()
Ref: http://matplotlib.sourceforge.net/faq/howto_faq.html#multiple-y-axis-scales
Output:
From matplotlib 3.1 onwards you may use ax.secondary_xaxis
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(1,13, num=301)
y = (np.sin(x)+1.01)*3000
# Define function and its inverse
f = lambda x: 1/(1+x)
g = lambda x: 1/x-1
fig, ax = plt.subplots()
ax.semilogy(x, y, label='DM')
ax2 = ax.secondary_xaxis("top", functions=(f,g))
ax2.set_xlabel("1/(x+1)")
ax.set_xlabel("x")
plt.show()
If You want your upper axis to be a function of the lower axis tick-values you can do as below. Please note: sometimes get_xticks() will have a ticks outside of the visible range, which you have to allow for when converting.
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
ax1 = fig.add_subplot(111)
ax1.plot(range(5), range(5))
ax1.grid(True)
ax2 = ax1.twiny()
ax2.set_xticks( ax1.get_xticks() )
ax2.set_xbound(ax1.get_xbound())
ax2.set_xticklabels([x * 2 for x in ax1.get_xticks()])
title = ax1.set_title("Upper x-axis ticks are lower x-axis ticks doubled!")
title.set_y(1.1)
fig.subplots_adjust(top=0.85)
fig.savefig("1.png")
Gives:
Answering your question in Dhara's answer comments: "I would like on the second x-axis these tics: (7,8,99) corresponding to the x-axis position 10, 30, 40. Is that possible in some way?"
Yes, it is.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
a = np.cos(2*np.pi*np.linspace(0, 1, 60.))
ax1.plot(range(60), a)
ax1.set_xlim(0, 60)
ax1.set_xlabel("x")
ax1.set_ylabel("y")
ax2 = ax1.twiny()
ax2.set_xlabel("x-transformed")
ax2.set_xlim(0, 60)
ax2.set_xticks([10, 30, 40])
ax2.set_xticklabels(['7','8','99'])
plt.show()
You'll get:
I'm forced to post this as an answer instead of a comment due to low reputation.
I had a similar problem to Matteo. The difference being that I had no map from my first x-axis to my second x-axis, only the x-values themselves. So I wanted to set the data on my second x-axis directly, not the ticks, however, there is no axes.set_xdata. I was able to use Dhara's answer to do this with a modification:
ax2.lines = []
instead of using:
ax2.cla()
When in use also cleared my plot from ax1.