How to plot two series with very different scales in python - 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)

Related

Add grid and change size in barh python

I am using matplotlib to draw horizontal plots. I want to add grids and change size of the plot to avoid overleap of the label. My code looks like this:
baseline = [0.5745,0.5282,0.4923,0.5077,0.5487,0.5385,0.5231]
low = [0.2653,0.3878,0.3673,0.5510,0.2245,0.5714,0.3265]
high = [0.5102,0.5102,0.3673,0.3877,0.5306,0.4286,0.49]
index = ['Bagging','Decision tree','Gussian Naive Bayes','Logistic regression','Random forest','SVM','k-NN']
df = pd.DataFrame({'Baseline': baseline,'ttd lower than median': low,'ttd higher than median': high}, index=index)
plt.figure(figsize = (6,12))
ax.yaxis.grid(color='gray', linestyle='dashed')
ax = df.plot.barh()
and the resulting plot looks like this:
However, it didn't show the grid and "plt.figure(figsize = (6,12))" seems did not work. How can I fix this? Thanks in advance!
Specify the location of the legend by using plt.legend
Making the figure larger won't necessarily make the legend fit better
Show the grid by using plt.grid()
plt.figure(figsize = (6,12)) didn't work, because the dataframe plot wasn't using this axes.
fig, ax = plt.subplots(figsize=(7, 12))
ax.yaxis.grid(color='gray', linestyle='dashed')
df.plot.barh(ax=ax) # ax=ax lets the dataframe plot use the subplot axes
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') # place the legend outside
plt.grid() # show the grid
Alternatively, use df.plot.barh(ax=ax, figsize=(7, 12))
p = df.plot.barh(figsize=(7, 8))
p.yaxis.grid(color='gray', linestyle='dashed')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')

Difficulties plotting two lines into one graph

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)

Smoother grid in a plot

I'm trying to plot a smoother grid in the background of this grid that's already plotted. This is what I've done so far. The grid follows my major ticks. I'd like this smoother grid to follow the minor ticks. Is this possible?
My code until now:
fig, ax = plt.subplots(figsize = (20,10))
ax.set_xticks(np.arange(0,round(max(datax)+1)))
ax.set_yticks(np.arange(0,round(max(datay)+1),step = 0.1))
ax.minorticks_on()
ax.grid(True)
plt.xlabel("Tensão (V)", fontsize = 14)
plt.ylabel("Corrente (mA)", fontsize = 14)
plt.title("Experimento 2", fontsize = 20)
ax.errorbar(datax,datay,xerr = sigmax, yerr = sigmay, fmt = ',')
ax.set(xlim= -1, ylim = 0)
P.S.: would you guys organize this code differently? I think it's a complete mess.
i want my grids to look like this
this is how they are now
What you want is the linestyle keyword argument for grid, along with the linewidth keyword argument.
Here's how you can use dotted lines for your grid, with thinner lines for the minor ticks:
ax.grid(True, which='major', linestyle=':', linewidth=1, color="black")
ax.grid(True, which='minor', linestyle=':', linewidth=0.5, color="black")
Here's the output (I used faked data since you did not provide a MWE):
You can fiddle with the linewidth parameter to have the lines appear thinner, or on the color to make them fainter.
You can also try other linestyles out, like dashed (linestyle='--').

Draw horizontal lines (matplotlib)

I try to run the code:
fig, ax = plt.subplots()
ax.plot(x, y, color="g")
ax.xaxis.set_major_locator(matplotlib.dates.YearLocator())
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%Y'))
hlines=[40,50]
ax.hlines(hlines, 1, len(x), color='g')
plt.show()
I expect it to draw something like this:
Drawing chart is not a problem, it works, but drawing horizontal lines doesn't work.
When I run my code it draws:
P.S. x created this way: dates to matplotlib dates
x.append(matplotlib.dates.date2num(datetime.strptime(date, '%Y%m%d')))
You are drawing a horizontal line from x-axis=1 to x-axis=len(x), which are just arbitrary integers that does not represent anything on your graph: your x-axis is much larger because you use matplotlib.dates.date2num. You need to properly assign the range for your horizontal line. For example:
ax.hlines(hlines, min(x), max(x), color='g')
or
ax.hlines(hlines,
matplotlib.dates.date2num(datetime.strptime(mindate, '%Y%m%d')),
matplotlib.dates.date2num(datetime.strptime(maxdate, '%Y%m%d')),
color='g')
or you could just use axhline:
ax.axhline(40, color='g')
ax.axhline(50, color='g')

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.

Categories