I have a plotting program that currently takes an array that goes from 12-2000 on both the x and y axis.
img2 = plt.imshow(data1,interpolation='nearest',cmap = cmap2, norm=MidpointNormalize(midpoint=p50)
,extent=[12,2000,12,2000], origin='lower')
This method works, but it gives me poor control over my axes. For instance, I want to convert my x and y points into a new coordinate system. The value at each location will stay the same, but the actual x and y will change by a factor of 2e-8*x^(4.3192). The problem is, this isn't in true log/log space.
ax = plt.subplot(111)
ax.set_yscale('log')
ax.set_xscale('log')
I tried changing the axes of the graph into log/log space, but they don't line up. What can I do?
Related
This excerpt from my code changes the value of the y axis labels from exponential to millions. Problem is it creates 2 figures. The first one is an x and y axis with no plot (and the scale of the x axis is used for the y axis as well), and then the 2nd figure is exactly what I want. It is a double bar graph.
I am guessing it has something to do with using f.plot.bar instead of plt.bar but I am not sure. I just want to get rid of the first figure than all will be well.
from matplotlib.ticker import FuncFormatter
def millions(x, pos):
'The two args are the value and tick position'
return '%1.1fM' % (x*1e-6)
formatter = FuncFormatter(millions)
fig, ax = plt.subplots()
ax = tempg.plot.bar(y=['Republican2016Votes', 'Democrat2016Votes'], rot=0,
color = ['DarkRed','Blue'])
ax.yaxis.set_major_formatter(formatter)
plt.show()
I'm trying to move the spines in a 3D matplotlib axes object.
This seems like a really simple issue, but I have not found any questions/answers that address this directly. I've included a list of my research on this topic at the bottom of this question.
I can set the position of the spines in matplotlib 2D plots. The following code:
import matplotlib.pyplot as plt, numpy as np
fig, axes = plt.subplots(1, 2)
r, theta = 1, np.linspace(0, 2*np.pi, 100)
x, y = r*np.cos(theta), r*np.sin(theta)
for ax in axes: # plot the same data on both axes
ax.plot(x, y)
ax.set_aspect("equal")
for spine in ax.spines.values(): # adjust spines on last active axis
spine.set_position(("data", 0))
produces:
However, when I try the same thing with a 3D axis...
z = np.zeros(x.shape) # exciting stuff
fig = plt.figure()
for i in range(2): # create two 3D subplots
ax = plt.subplot(1,2,i+1, projection="3d", aspect="equal")
plt.plot(x, y, z)
for spine in ax.spines.values(): # adjust spines on last active axis
spine.set_position(("data", 0))
the above code gives me:
I.e. no effect, even though the code still runs. Also, for the 3D axes, ax.spines looks like:
OrderedDict([('left', <matplotlib.spines.Spine at 0x120857b8>),
('right', <matplotlib.spines.Spine at 0xfd648d0>),
('bottom', <matplotlib.spines.Spine at 0xe89e4e0>),
('top', <matplotlib.spines.Spine at 0xe89eef0>)])
I'm not sure what "left", "right", "bottom", "top" refer to in the context of a 3D axis. I've tried changing other properties like colour of the spines; no luck there either. How can I get hold of the actual x, y, z spines on the axes?
Research:
searching "matplotlib spines 3d" in stackoverflow gives 5 results (including this question) at the time of writing.
The mplot3d documentation doesn't mention spines at all.
This question shows how to set the pane colour with ax.w_xaxis.set_pane_color(), but there is no similar ax.w_zaxis.set_spine... method.
This question shows how to set the spine colour using ax.w_zaxis.line.set_color(). I thought about making a horrible workaround to set ax.w_zaxis.line.set_data manually, but it only has x and y data; no z! Even the x and y axes don't have z data.
There seems to be no obvious way to do this at the moment. Setting the spines when the axis projection is 3D is not implemented. However, there is a small hack here.
The ax.spines setting is for 2D rendering. When you set projection=3d in the initialization of the figure, certain 2D properties (like ax.spines, etc.) are ignored. It's why you don't get any response when you set the 2D spines.
The 3D figure axis line (the thick black line for each axis) locations are determined by the parameter ax.xaxis._axinfo['juggled'] (and similarly for y and z axes). This specifies which of the six outer boundaries of a 3D plot bounding box are plotted as thick black lines.
You can shift the position of the axis line for each of x,y,z axis by overwriting the juggled value, which specifies which axis lines are the main ones, as the following example for the x axis,
the default setting, ax.xaxis._axinfo['juggled'] = (1,0,2)
new setting, ax.xaxis._axinfo['juggled'] = (2,0,1)
The parameters for all the six outer boundaries are,
I have an image plot, representing a matrix, with two axes. The y axis on th left of my image plot represents the rows and the x axis represents the column, while each grid cell represents the value as a function of x and y.
I'd like to plot my y-axis in another form on the right side of my image plot, which takes on much smaller values, but should still be in the same positions as the y-axis on the left, as the values are just different forms of one another. The problem is that when I use fig.twinx()and go to plot the y axis, it doesn't even show up! Does anyone know what's gong on? Thanks.
Current code:
# Setup the figure
fig5 = pyplot.figure(5, figsize=(10,9), facecolor='white')
pyplot.gcf().clear()
# plt.rc('xtick', labelsize=20)
# plt.rc('ytick', labelsize=20)
plt.rcParams.update({'font.size': 18})
fig5ax = pyplot.axes()
# Code to calculate extent based on min/max range and my x values
implot = pyplot.imshow(valgrid, extent=MyExtent , aspect='auto', vmin = myVmin, vmax = myVmax)
fig5ax.yaxis.set_major_formatter(plt.ticker.FixedFormatter([str(x) for x in ranges]))
fig5ax.yaxis.set_major_locator(plt.ticker.FixedLocator(ranges))
fig5Ax2 = fig5ax.twinx()
fig5Ax2.yaxis.set_major_formatter(plt.ticker.FixedFormatter([str(x) for x in time]))
# Setting locater the same as ranges, because I want them to line up
# as they are different forms of the same y value
fig5Ax2.yaxis.set_major_locator(plt.ticker.FixedLocator(ranges))
pyplot.show()
The answer was:
fig5Ax2.yaxis.set_view_interval(minRange, maxRange)
I am working on Python with the matplotlib library and I have a problem with color maps dimension.
I have some target variable target that depends on two variables x and y - i.e. my data target is a matrix with the variable x being rows and y columns. I want to represent target in a color map with respect to x and y. The problem is that I have more values for x than for y, hence if I plot a color map I get a rectangle - a rather ugly one because I have many more values for x than for y.
I would rather have rectangular "pixels" in the color map and a square map, rather than square "pixels" but a rectangular color map - or at least I would like to compare the two visualizations.
My question is: how can I force the color map to be square?
This is my current code - the cmap variable simply allows me to define my custom color scale:
import matplotlib.pyplot as plt
import matplotlib.pyplot as clr
target = ...
cmap = clr.LinearSegmentedColormap.from_list('custom blue',
['#DCE6F1','#244162'],
N=128)
plt.matshow(target, cmap=cmap)
plt.colorbar(cmap='custom blue')
What's your matplotlib version?
If it's newer than 1.1.0 then you can try this:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(np.random.rand(32, 64), cmap='rainbow', aspect=2)
plt.show()
This gives you rectangular pixels with square figure shape.
You should replace np.random.rand(32, 64) by your data, and define the aspect ratio you like. Also, please refer to this post. There are other solutions you might be interested in.
Andreas's answer works on my computer. You might see a slightly different result that with your code because imshow() will by default interpolate the image, therefore the picture will be different compared to matshow(). But the aspect parameter works on both. So either feed it to matshow(), or disable the interpolation in imshow():
fig = plt.figure()
ax = fig.add_subplot(111)
ax.matshow(np.random.rand(32, 64), cmap='rainbow', aspect=2)
plt.show()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(np.random.rand(32, 64), cmap='rainbow', aspect=2, interpolation="None")
plt.show()
I would like to plot a 2D discretization rectangular mesh with non-regular
x y axes values, e.g. the typical discretization meshes used in CFD.
An example of the code may be:
fig = plt.figure(1,figsize=(12,8))
axes = fig.add_subplot(111)
matplotlib.rcParams.update({'font.size':17})
axes.set_xticks(self.xPoints)
axes.set_yticks(self.yPoints)
plt.grid(color='black', linestyle='-', linewidth=1)
myName = "2D.jpg"
fig.savefig(myName)
where self.xPoints and self.yPoints are 1D non-regular vectors.
This piece of code produce a good discretization mesh, the problem are the
xtics and ytics labels because they appear for all values of xPoints and yPoints (they overlap).
How can I easily redefine the printed values in the axes?
Let's say I only want to show the minimum and maximum value for x and y and not all values from the discretization mesh.
I cann't post a example-figure because it is the first time I ask something here (I can send it by mail if requested)
the problem is that you explicitly told matplotlib to label each point when you wrote:
axes.set_xticks(self.xPoints)
axes.set_yticks(self.yPoints)
comment out those lines and see what the result looks like.
Of course, if you only want the first and last point labelled, it becomes:
axes.set_xticks([self.xPoints[0], self.xPoints[-1]])
...
If the gridline was specified by axes.set_xticks(), I don't think it would be possible to show ticks without overlap in your case.
I may have a solution for you:
...
ax = plt.gca()
#Arr_y: y-direction data, 1D numpy array or list.
for j in range(len(Arr_y)):
plt.hline(y = Arr_y[j], xmin = Arr_x.min(), xmax = Arr_x.max(), color = 'black')
#Arr_x: x-direction data, 1D numpy array or list.
for i in range(len(Arr_x)):
plt.vline(x = Arr_x[i], ymin = Arr_y.min(), ymax = Arr_y.max(), color = 'black')
#Custom your ticks here, 1D numpy array or list.
ax.set_xticks(Arr_xticks)
ax.set_yticks(Arr_yticks)
plt.xlim(Arr_x.min(), Arr_x.max())
plt.ylim(Arr_y.min(), Arr_y.max())
plt.show()
...
hlines and vlines are horizontal and vertical lines, you can specify those lines with boundary data in both x and y directions.
I tried it with 60×182 non uniform mesh grid which cost me 1.2s, hope I can post a picture here.