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()
Related
I have written the following minimal Python code in order to plot various functions of x on the same X-axis.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from cycler import cycler
cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']
xlabel='$X$'; ylabel='$Y$'
### Set tick features
plt.tick_params(axis='both',which='major',width=2,length=10,labelsize=18)
plt.tick_params(axis='both',which='minor',width=2,length=5)
#plt.set_axis_bgcolor('grey') # Doesn't work if I uncomment!
lines = ["-","--","-.",":"]
Nlayer=4
f, axarr = plt.subplots(Nlayer, sharex=True)
for a in range(1,Nlayer+1):
X = np.linspace(0,10,100)
Y = X**a
index = a-1 + np.int((a-1)/Nlayer)
axarr[a-1].plot(X, Y, linewidth=2.0+index, color=cycle[a], linestyle = lines[index], label='Layer = {}'.format(a))
axarr[a-1].legend(loc='upper right', prop={'size':6})
#plt.legend()
# Axes labels
plt.xlabel(xlabel, fontsize=20)
plt.ylabel(ylabel, fontsize=20)
plt.show()
However, the plots don't join together on the X-axis and I failed to get a common Y-axis label. It actually labels for the last plot (see attached figure). I also get a blank plot additionally which I couldn't get rid of.
I am using Python3.
The following code will produce the expected output :
without blank plot which was created because of the two plt.tick_params calls before creating the actual fig
with the gridspec_kw argument of subplots that allows you to control the space between rows and cols of subplots environment in order to join the different layer plots
with unique and centered common ylabel using fig.text with relative positioning and rotation argument (same thing is done to xlabel to get an homogeneous final result). One may note that, it can also be done by repositioning the ylabel with ax.yaxis.set_label_coords() after an usual call like ax.set_ylabel().
import numpy as np
import matplotlib.pyplot as plt
cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']
xlabel='$X$'; ylabel='$Y$'
lines = ["-","--","-.",":"]
Nlayer = 4
fig, axarr = plt.subplots(Nlayer, sharex='col',gridspec_kw={'hspace': 0, 'wspace': 0})
X = np.linspace(0,10,100)
for i,ax in enumerate(axarr):
Y = X**(i+1)
ax.plot(X, Y, linewidth=2.0+i, color=cycle[i], linestyle = lines[i], label='Layer = {}'.format(i+1))
ax.legend(loc='upper right', prop={'size':6})
with axes labels, first option :
fig.text(0.5, 0.01, xlabel, va='center')
fig.text(0.01, 0.5, ylabel, va='center', rotation='vertical')
or alternatively :
# ax is here, the one of the last Nlayer plotted, i.e. Nlayer=4
ax.set_xlabel(xlabel)
ax.set_ylabel(ylabel)
# change y positioning to be in the horizontal center of all Nlayer, i.e. dynamically Nlayer/2
ax.yaxis.set_label_coords(-0.1,Nlayer/2)
which gives :
I also simplified your for loop by using enumerate to have an automatic counter i when looping over axarr.
I'm trying to use pyplot to do linear modeling, and I've run across a problem. When I make a plot of the data, pyplot wants to put decimal percentages along the X and Y axis. I've tried a few different things to make it go away. I want to keep some tick labels, so I've tried various methods of adding my own tick labels, and that works, however, it still prints its own tick labels on top.
So at the origin it says 0.0, then a fifth of the way along the axis it says 0.2, so on until the end of the axis it says 1.0.
Example image of the problem:
fig = plt.figure(figsize = (10,10))
big_plot = fig.add_subplot(111)
data_plot = fig.add_subplot(211)
residual_plot = fig.add_subplot(212)
data_plot.plot(x,y,'ro')
data_plot.errorbar(x,model,sigma)
residual_plot.plot(x,residuals,'b*')
data_plot.set_title("Data")
data_plot.set_ylabel(y_label)
residual_plot.set_title("Residuals")
residual_plot.set_ylabel("Residual Value")
big_plot.set_xlabel(x_label)
plt.show()
Does anyone know how to clear those tick labels and add my own? Thank you.
In your case, you are creating three plots, but only plotting data on two of them. The big_plot is axis is plotted with the default tick marks and it is the source of the extra tick marks that you don't want.
Instead, just remove this axis and label the bottom x-axis by assigning the label to data_plot.
fig = plt.figure(figsize = (10,10))
data_plot = fig.add_subplot(211)
residual_plot = fig.add_subplot(212)
data_plot.plot(x,y,'ro')
data_plot.errorbar(x,model,sigma)
residual_plot.plot(x,residuals,'b*')
data_plot.set_title("Data")
data_plot.set_ylabel(y_label)
residual_plot.set_title("Residuals")
residual_plot.set_ylabel("Residual Value")
data_plot.set_xlabel(x_label)
plt.show()
This is to clarify the question title. Say you have four lists of integers, with which you want to produce a scatter plot:
a=[3,7,2,8,12,17]
b=[9,4,11,7,6,3]
c=[9,3,17,13,10,5]
d=[5,1,1,14,5,8]
You also have a function, for simplicity f(x)=1/x, that applies to all lists, so that:
from __future__ import division
a1=[1/i for i in a]
b1=[1/i for i in b]
c1=[1/i for i in c]
d1=[1/i for i in d]
My question: how to add a second y axis, knowing that the values returned by the function range from 0.06 to 1.0, without using any of the a1, b1, c1, d1 lists in the scatter plots?
What I am saying is: if you produce the following scatter plots in the traditional way, how can you then add the second y axis based on the values of a1, b1, c1, d1, without having any series using them in the plot itself?
import matplotlib.pyplot as plt
plt.scatter(a,b,c='red',label='reds')
plt.scatter(c,d,c='blue',label='blues')
plt.legend(loc='best')
This is the scatter without the second y axis:
And this is a made up version of the same one, including the second y axis discussed so far:
NB: This question is different from this, in that I am not trying to plot with different scales. I only want to add a second axis with the relevant values.
To make sure the numbers on the new axis are in the corresponding position to their inverses:
import matplotlib.pylab as plt
a=[3,7,2,8,12,17]
b=[9,4,11,7,6,3]
c=[9,3,17,13,10,5]
d=[5,1,1,14,5,8]
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(a,b,c='red',label='reds')
ax.scatter(c,d,c='blue',label='blues')
ax.legend(loc='best')
ax.set_ylabel('Y')
# make shared y axis
axi = ax.twinx()
# set limits for shared axis
axi.set_ylim(ax.get_ylim())
# set ticks for shared axis
inverse_ticks = []
label_format = '%.3f'
for tick in ax.get_yticks():
if tick != 0:
tick = 1/tick
inverse_ticks.append(label_format % (tick,))
axi.set_yticklabels(inverse_ticks)
axi.set_ylabel('1/Y')
fig.tight_layout()
fig.show()
And you can also do it for the X axis:
# make shared x axis
xaxi = ax.twiny()
# set limits for shared axis
xaxi.set_xlim(ax.get_xlim())
# set ticks for shared axis
inverse_ticks = []
label_format = '%.3f'
for tick in ax.get_xticks():
if tick != 0:
tick = 1/tick
inverse_ticks.append(label_format % (tick,))
xaxi.set_xticklabels(inverse_ticks)
xaxi.set_xlabel('1/X')
Just make shared y axis and set desired limits and ticks for new axis like here:
import matplotlib.pylab as plt
import numpy as np
a=[3,7,2,8,12,17]
b=[9,4,11,7,6,3]
c=[9,3,17,13,10,5]
d=[5,1,1,14,5,8]
plt.scatter(a,b,c='red',label='reds')
plt.scatter(c,d,c='blue',label='blues')
plt.legend(loc='best')
ax = plt.gca()
# make shared y axis
ax2 = ax.twinx()
# set limits for shared axis
ax2.set_ylim([0,1])
# set ticks for shared axis
plt.yticks(np.arange(0.06, 1, 0.14))
plt.show()
I am trying to rotate the title of the Y axis so it is horizontal. I do not want the tick labels horizontal just the title of the Y axis. I have to use subplots as I am making multiple plots at once. Here is the below script in which I have tried to rotate the Y axis title.
import matplotlib.pyplot as plt
import sys
fig, ax = plt.subplots()
ax.set_title(r'$\alpha$ > \beta_i$', fontsize=20)
ax.set(xlabel='meters $10^1$', ylabel=r'Hertz $(\frac{1}{s})$')
ax.set(xlabel=r's(t) = \mathcal(A)\/\sin(2 \omega t)', ylabel=r'Hertz $(\frac{1}{s})$')
ax.set(ylabel="North $\uparrow$",fontsize=9,rotate=90)
plt.show()
When I run it I get an error:
TypeError: There is no AxesSubplot property "rotate"
How can I tweak this program so that the Y axis is rotating horizontally?
By using ax.set you are attempting to set properties of the axes rather than properties of the ylabel text object.
Rather than using ax.set you can instead use xlabel and ylabel to create the x and y labels and pass in kwargs to modify their appearance. Also the property name is rotation rather than rotate. Also you'll want to set the rotation to 0 as the default is 90 which is why it's rotated in the first place.
plt.title(r'$\alpha > \beta_i$', fontsize=20)
plt.xlabel(r'meters $10^1$', fontsize=9)
plt.ylabel("North $\uparrow$", fontsize=9, rotation=0)
In a Python plot I would like to use a secondary x-axis to display some alternative values. I'm also quite fond of the latex fonts, and would like those fonts to present throughout the plot. However, I find that when I set up my secondary axis, the latex font disappears. Here's a minimum working example:
import numpy as np
import matplotlib.pyplot as plt
Xvalues = np.linspace(0,10,100)
Yvalues = np.sqrt(Xvalues)
Xticks = np.linspace(0,10,6)
AltXvalues = np.log10(Xvalues+1)
AltLabels = ["%.2f" % x for x in AltXvalues] # Round these values
fig = plt.figure()
plt.rcParams['text.usetex'] = True
ax1 = fig.add_subplot(1,1,1)
ax1.plot(Xvalues, Yvalues)
ax1.set_xticks(Xticks)
ax1.set_xlabel('$x_1$')
ax1.set_ylabel('$y$')
ax2 = ax1.twiny()
ax2.set_xlabel('$\\log_{10}\\,(x_1+1)$')
ax2.set_xticks(Xticks)
ax2.set_xticklabels(AltLabels)
plt.show()
How can I ensure that the latex font is continued on the secondary axis?
Its because you are making those labels into strings when you set AltLabels. The different font you see on the primary axis tick labels is because those labels are printed in LaTeX's math-mode. So, the simple fix is to add the math-mode operators to the AltLabel strings:
AltLabels = ["$%.2f$" % x for x in AltXvalues] # Round these values
(Note the $ signs)