Difficulties plotting two lines into one graph - python

I have faced a problem with matplotlib. I have four lists of data, some rates and their corresponding years, some values and their corresponding years. I'm trying to write two lines into one graph, so that left and right Y axes have different scales, but the both lines share a common X axis. The other list of years is also little shorter than the other.
So this is what I currently have
gdp_years, gdp_rates = get_ordered_values(gdp_url)
un_years, un_rates = get_ordered_values(un_url)
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel('Year')
ax1.set_ylabel('GDP', color=color)
ax1.plot(gdp_rates, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx()
color = 'tab:blue'
ax2.set_ylabel('UN', color=color)
ax2.plot(un_rates, color=color)
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout()
plt.show()
This is the graph I have now.
Those scales seem to be okay, but X axis is not correct. I'm trying to get those year labels from the list to represent X axis, but I can't figure it out. Years should be from 1960 til 2018, but now the X axis shows from 0 to 60. Because of this I believe also the blue line is wrongly placed.

You forgot to plot the x-values, i.e. respective years. You should do
ax1.plot(gdp_years, gdp_rates, color=color)
ax2.plot(un_years, un_rates, color=color)

Related

Add a tick to top x axis

I do not really understand why this code is not working
fig, ax = plt.subplots()
ax.plot(Vg_vec, sigma_i)
ax.set_xlabel('$V_\mathrm{g}$ ($\mathrm{V}}$)')
ax.set_ylabel('$\sigma_\mathrm{i}$ ($\mathrm{C/m^2}$)')
peaks, _ = find_peaks(sigma_i, height=0.006415)
plt.axvline(Vg_vec[peaks], color='red')
ax2 = ax.twiny()
ax2.set_xticks(Vg_vec[peaks])
ax2.tick_params(axis='x', colors='red')
My result
There should be a red tick in the top x axis.
Thanks
the issue with your code is twofold:
By using twiny instead of secondary_axis, the upper x-axis will be different to the bottom one, and I assume you want them to be the same. That's extra work to fix, so I used secondary_axis in my example.
This is something I don't know why it happens, but it has happened to me before. When supplying the tick values, the first one is always "ignored", so you have to supply two or more values. I used 0, but you can use anything.
Here's my code:
fig, ax = plt.subplots()
ax.plot(Vg_vec, sigma_i)
ax.set_xlabel('$V_\mathrm{g}$ ($\mathrm{V}}$)')
ax.set_ylabel('$\sigma_\mathrm{i}$ ($\mathrm{C/m^2}$)')
peaks, _ = find_peaks(sigma_i, height=None)
plt.axvline(Vg_vec[peaks], color='red')
ax2 = ax.secondary_xaxis('top')
ax2.tick_params(axis='x', color='red')
ax2.set_xticks([0, *Vg_vec[peaks]], minor=False)
And the resulting plot:

How to plot two series with very different scales in python

I'm a beginner in python. I have to plot two graphs in the same plot. One of my graphs is velocity, which ranges between (-1,1), and the other one is groundwater, which ranges between (10,12). When I use the following code, the graphs become very small.
ax1 = plt.subplot(111)
ax2 = ax1.twinx()
df=pd.read_excel ('final-all-filters-0.6.xlsx')
df['Date']=pd.to_datetime(df['Date'])
date = df['Date']
gwl = df['gwl']
v =df['v']
plt.plot(date,gwl, color='deepskyblue',linewidth=2)
plt.plot(date,v, color='black',linewidth=2)
ax1.grid(axis='y')
ax1.xaxis.set_major_locator(matplotlib.dates.YearLocator())
ax1.xaxis.set_minor_locator(matplotlib.dates.MonthLocator((1,3,5,7,9,11)))
ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("\n%Y"))
ax1.xaxis.set_minor_formatter(matplotlib.dates.DateFormatter("%b"))
ax1.grid(which='minor', alpha=0.3, linestyle='--')
ax1.grid(which='major', alpha=2)
for spine in ax1.spines.values():
spine.set_edgecolor('gray')
ax1.tick_params(axis='x', which='both', colors='gray')
ax1.tick_params(axis='y', colors='gray')
ax1.set_ylabel('v', color='g')
ax2.set_ylabel('GWL', color='b')
plt.show()
But when I add the ax1.set_ylim(-1, 1)and ax2.set_ylim(10, 12) to my code, one of the graph was disappered!
I think it does plot the black graph, but it's out of range. You can check that by adding 11 or something to the black plot value.
Maybe you can try using ax2.set_yticks(np.arange(-1, 1, 0.5)) instead of set_ylim and/or using ax2.autoscale(enable=True, axis=y)

Align x and y axis with twinx twiny in log scale

I want to create a plot with two x axis and also two y axis. I am using twiny and twinx to do it. The secondary axis are just a rescaling of the original ones, so I'm applying a transformations to get the ticks. The problem is that I am in log scale, so the separation between the ticks does not match between the original and the twin ax. Moreover, the second x axis has other values that I don't want.
Let's follow an example to explain better:
#define the transformations I need
h=0.67
def trasf_log(y):
y_ = 10**y
return y_/h
def trasf_sigma(x):
return 1.68/x
#plot in log scale and with ticks that I choose
fig,ax = plt.subplots(1)
ax.plot(x,y0)
ax.set_ylim(1.0,2.4)
ax.set_xlim(0.6,5)
ax.set_xscale('log')
ax.set_yscale('log')
ax.set_xticks([0.6,0.8,1,2,3,4])
ax.set_yticks([1.0,1.2,1.4,1.6,1.8,2.0,2.2,2.4])
ax.xaxis.set_major_formatter(ScalarFormatter())
ax.yaxis.set_major_formatter(ScalarFormatter())
ax.ticklabel_format(axis='both', style='plain')
ax.set_xlabel(r'$\nu$', fontsize=20)
ax.set_ylabel(r'$\log_{10}Q$', fontsize=20)
ax.tick_params(labelsize=15)
#create twin axes
ax1 = ax.twinx()
ax1.set_yscale('log')
ymin,ymax=ax.get_ylim()
ax1.set_ylim((trasf_log(ymin),trasf_log(ymax)))
ax1.set_yticks(trasf_log(ax.get_yticks()))
ax1.yaxis.set_major_formatter(ScalarFormatter())
ax1.ticklabel_format(axis='y', style='plain')
ax1.tick_params(labelsize=15,labelleft=False,labelbottom=False,labeltop=False)
ax1.set_ylabel(r'$Q$', fontsize=20)
ax2 = ax.twiny()
ax2.set_xscale('log')
xmin,xmax=ax.get_xlim()
ax2.set_xlim((trasf_sigma(xmin),trasf_sigma(xmax)))
ax2.set_xticks(trasf_sigma(ax.get_xticks()))
ax2.xaxis.set_major_formatter(ScalarFormatter())
ax2.ticklabel_format(axis='x', style='plain')
ax2.tick_params(labelsize=15,labelleft=False,labelbottom=False,labelright=False)
ax2.set_xlabel(r'$\sigma $', fontsize=20)
ax.grid(True)
fig.tight_layout()
plt.show()
This is what I get:
The values of the new x and y axis are not aligned with the original ones. For example, on the two x axis the values 1 and 1.68 should be aligned. Same thing for the y axis: 1.2 and 23.7 should be aligned.
Moreover, I don't understand where the other numbers on the second x axis are coming from.
I tried already applying Scalar Formatter to each axis with 'plain' style, but nothing changes.
I also tried using secondary_axis, but I could not find a solution as well.
Anyone knows a solution?

Two subplots coming out too long (length)

I'm attempting to plot two bar charts using matplotlib.pyplot.subplots. I've created subplots within a function, but when I output the subplots they are too long in height and not long enough in width.
Here's the function that I wrote:
def corr_bar(data1, data2, method='pearson'):
# Basic configuration.
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(7, 7))
ax1, ax2 = axes
corr_matrix1 = data1.corr(method=method)
corr_matrix2 = data2.corr(method=method)
cmap = cm.get_cmap('coolwarm')
major_ticks = np.arange(0, 1.1, 0.1)
minor_ticks = np.arange(0, 1.1, 0.05)
# Values for plotting.
x1 = corr_matrix1['price'].sort_values(ascending=False).index
x2 = corr_matrix2['price'].sort_values(ascending=False).index
values1 = corr_matrix1['price'].sort_values(ascending=False).values
values2 = corr_matrix2['price'].sort_values(ascending=False).values
im1 = ax1.bar(x1, values1, color=cmap(values1))
im2 = ax2.bar(x2, values2, color=cmap(values2))
# Formatting for plot 1.
ax1.set_yticks(major_ticks)
ax1.set_yticks(minor_ticks, minor=True)
plt.setp(ax1.get_xticklabels(), rotation=45, ha='right', rotation_mode='anchor')
ax1.grid(which='both')
ax1.grid(which='minor', alpha=0.4)
ax1.grid(which='major', alpha=0.7)
ax1.xaxis.grid(False)
# Formatting for plot 2.
ax2.set_yticks(major_ticks)
ax2.set_yticks(minor_ticks, minor=True)
plt.setp(ax2.get_xticklabels(), rotation=45, ha='right', rotation_mode='anchor')
ax2.grid(which='both')
ax2.grid(which='minor', alpha=0.4)
ax2.grid(which='major', alpha=0.7)
ax2.xaxis.grid(False)
fig.tight_layout()
plt.show()
This function (when run with two Pandas DataFrames) outputs an image like the following:
I purposely captured the blank right side of the image as well in an attempt to better depict my predicament. What I want is for the bar charts to be appropriately sized in height and width as to take up the entire space, rather than be elongated and pushed to the left.
I've tried to use the ax.set(aspect='equal') method but it "scrunches up" the bar chart. Would anybody happen to know what I could do to solve this issue?
Thank you.
When you define figsize=(7,7) you are setting the size of the entire figure and not the subplots. So your entire figure must be a square in this case. You should change it to figsize=(14,7) or use a number larger than 14 to get a little bit of extra space.

Create plot in matplotlib with appropriately sized axis

In the figure below, x-axis goes upto 54 and y-axis upto 8. However, the size of both is same. I would like to make the figure proportionate. I.e. x-axis should be longer than y-axis by a ratio of 54/8. Any suggestions?
fig = plt.figure()
plt.xlim(0,54)
plt.ylim(0,8)
#plt.axis('off')
plt.show()
plt.close()
Just add the following line:
fig = plt.figure()
plt.xlim(0,54)
plt.ylim(0,8)
plt.axes().set_aspect('equal')
plt.show()

Categories