matplotlib plotting a line which makes fixed angle with x-axis - python-2.7

I have a fixed point, and I want to draw a line which goes through this fixed point, and also makes 45 degrees angle i.e. slope 1 with the x-axis.
How can i do it with matplotlib ?

This can be done setting the aspect ratio of the plot to 'equal' and using the right coordinates, for instance (you can also use ax.set_aspect):
import matplotlib.pyplot as plt
xs = [1,2]
ys = [0,1]
ax = plt.subplot(aspect='equal')
ax.plot(xs, ys, '-')
ax.set_xlim(0,5)
ax.set_ylim(0,5)
plt.show()

Related

How can I remove the negative sign from y tick labels in matplotlib.pyplot figure?

I am using the matplotlib.pylot module to generate thousands of figures that all deal with a value called "Total Vertical Depth(TVD)". The data that these values come from are all negative numbers but the industry standard is to display them as positive (I.E. distance from zero / absolute value). My y axis is used to display the numbers and of course uses the actual value (negative) to label the axis ticks. I do not want to change the values, but am wondering how to access the text elements and just remove the negative symbols from each value(shown in red circles on the image).
Several iterations of code after diving into the matplotlib documentation has gotten me to the following code, but I am still getting an error.
locs, labels = plt.yticks()
newLabels = []
for lbl in labels:
newLabels.append((lbl[0], lbl[1], str(float(str(lbl[2])) * -1)))
plt.yticks(locs, newLabels)
It appears that some of the strings in the "labels" list are empty and therefore the cast isn't working correctly, but I don't understand how it has any empty values if the yticks() method is retrieving the current tick configuration.
#SiHA points out that if we change the data then the order of labels on the y-axis will be reversed. So we can use a ticker formatter to just change the labels without changing the data as shown in the example below:
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
#ticker.FuncFormatter
def major_formatter(x, pos):
label = str(-x) if x < 0 else str(x)
return label
y = np.linspace(-3000,-1000,2001)
fig, ax = plt.subplots()
ax.plot(y)
ax.yaxis.set_major_formatter(major_formatter)
plt.show()
This gives me the following plot, notice the order of y-axis labels.
Edit:
based on the Amit's great answer, here's the solution if you want to edit the data instead of the tick formatter:
import matplotlib.pyplot as plt
import numpy as np
y = np.linspace(-3000,-1000,2001)
fig, ax = plt.subplots()
ax.plot(-y) # invert y-values of the data
ax.invert_yaxis() # invert the axis so that larger values are displayed at the bottom
plt.show()

Matplotlib Subplot - Unexpected Y axis ticks

I am working with matplotlib subplots. This is the skeleton of my code:
import matplotlib.pyplot as plt
from matplotlib import gridspec
plt.close('all')
f, axarr = plt.subplots(2, sharex=True,)
gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1])
axarr[0] = plt.subplot(gs[0])
axarr[1] = plt.subplot(gs[1])
axarr[0].set_ylim([-10,10])
axarr[1].set_ylim([-1,1])
plt.tight_layout()
f.subplots_adjust(hspace=0)
plt.show()
This is the output that I get from this code.
As one can see, in the left y-axis, I get ytick labels which overlap on top of each other and 'weird' y-axis tick labels (0) in the y-axis on the right hand side. How can I solve this? I will be thankful to have help here.
Those are the x labels of the upper subplot which are only partially hidden by the lower subplot. Turn them off if you like,
axarr[0].set_xticklabels([])
In order for the ticklabels not to overlap you may change the ylimits of the axes,
axarr[0].set_ylim([-10.5,10])
axarr[1].set_ylim([-1,1.2])

How to specify 2D histogram image size and scale in pyplot

I wish to produce a series of 2D histograms using pyplot.
I want to be able to specify the size and scale (or aspect ratio) of the generated image. In addition to this, I would like to remove the ticks and axes labels and borders.
This does not seem to be possible in the arguments to the plt.hist2d() method.
Rather than share my (rather complex) code, I post the pyplot demo script. If what I want is possible with this code, then it will be possible with mine.
import matplotlib.pyplot as plt
import numpy as np
x = np.random.randn(1000)
y = np.random.randn(1000) + 5
# normal distribution center at x=0 and y=5
plt.hist2d(x, y, bins=40)
plt.show()
Thanks for your help in advance.
Specifying the aspect alone will not help, you need the figure size in width or height in addition.
To get rid of the margins you can use subplots_adjust. And in order to turn the axes off you need axis("off").
import matplotlib.pyplot as plt
import numpy as np
x = np.random.randn(1000)
y = np.random.randn(1000) + 5
width=4 # inch
aspect=0.8 # height/width ratio
height = width*aspect
plt.figure(figsize=(width, height ))
plt.hist2d(x, y, bins=40)
plt.subplots_adjust(bottom=0, top=1, left=0, right=1)
plt.gca().axis("off")
plt.show()
The figsize should do what you want:
plt.figure(figsize=(20,10))
plt.hist2d(x, y, bins=40)
plt.show()
The following snippet shows how to quickly and easily
set the figure size (and implicitly the aspect ratio)
disable the axis bounding box and tick annotations
set the axis to fill the whole figure (removes borders)
save the resulting figure to an image file.
.
import matplotlib.pyplot as plt
import numpy as np
x = np.random.randn(1000)
y = np.random.randn(1000) + 5
plt.figure(figsize=[7, 2]) # set figure dimensions to weird but illustrative aspect ratio
plt.hist2d(x, y, bins=40)
plt.box(False) # disable axis box
plt.xticks([]) # no x axis ticks
plt.yticks([]) # no y axis ticks
plt.subplots_adjust(left=0, right=1, top=1, bottom=0) # remove borders
plt.savefig('output.png')
plt.show()

Scatterplot in Matplotlib with its natural line

While joining the points given by scatterplot in matplotlib, I only want to get the natural fit, and not x-y , which becomes a zig-zag as shown below.
How can I do this in matpotlib ?
PS: I don't want fitting polynomial/regression line, just the regular natural line
from pylab import *
import matplotlib.pyplot as plt
//Generate some x-y data for yourself...
x=[key for key in my_dict.keys()]
y=[imp for imp in my_dict.values()]
xlim([min(x),max(x)])
ylim([min(y),max(y)])
plt.scatter(x,y)
I get :
On doing basic plot along with this, I get connected, but overlapping lines
plt.plot(x, y, '-o')
plt.show()
What I would like to have:
Related q/a but doesn't exactly fit my case
Fallback Alternatives - Fit a n-th degrees polynomial as here -
Multivariate (polynomial) best fit curve in python?
Edit :- I tried the code below as suggested
[x, y] = zip(*sorted(zip(x, y), key=lambda x: x[0])) ###
plt.plot(x, y, '-o')
here's what I now get, butI am looking for something more smoother.
In order for plt.plot(x, y, '-o') to work, you will need to sort your data in x so that the line doesn't appear disjointed. You can do that with something like this:
[x, y] = zip(*sorted(zip(x, y), key=lambda x: x[0]))
That will sort both data, with x as the key.

matplotlib zorder of elements in polar plot superimposed on cartesian plot

I'm having a difficulty controlling the zorder of the elements of a polar plot superimposed on a cartesian plot.
Consider this example:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(1, 1, marker='*', s=2000, c='r', zorder=2)
ax2 = fig.add_axes(ax.get_position(), frameon=False, polar=True)
ax2.scatter(1., 0.1, marker='*', s=1000, c='b', zorder=1)
plt.xlim(0, 2)
plt.ylim(0, 2)
plt.show()
The result is:
It looks like matplotlib ignored the zorder of scatter plots. I would expect the red star to be on top of the blue one.
Could you please explain what I'm doing wrong here?
I found one question, which is kind of similar to mine, but concerns ticklines and grids instead. Maybe it's the same bug?
P.S. I'm running Linux x86_64 with Python 2.7.6 and matplotlib 1.3.1.
The problem is that you are setting the z-order of the marks on different axes ax and ax2 but since ax2 has a greater z-order all the plots in it will be on top of ax. One solution could be to set a higher z-order to ax but then you need to make the background transparent or set frameon=False (and that's maybe not desirable for your case), this is a demonstration of what I'm saying:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(1, 1, marker='*', s=2000, c='r', zorder=2)
ax2 = fig.add_axes(ax.get_position(), frameon=False, polar=True)
ax2.scatter(1., 0.1, marker='*', s=1000, c='b', zorder=1)
ax.set_zorder(3)
ax.patch.set_facecolor('none')
#ax.patch.set_visible(False)
plt.xlim(0, 2)
plt.ylim(0, 2)
plt.show()
Plot: