multiple axis not starting at zero - python

I Darw a graph with mutliple axix, have several questios:
why the left y-axsis is not satrting from zero. (I mean the zero point
is not at the begining of the y-axix).
I only want major grid for the x-axis (a major grid line for each week) but the code add a mjor
grid for the y-axix also.
How can i add minor grid for y-axix (the red one (ax2))
i want to change the color for the x-axis labels (Dates) color to black
import matplotlib.pyplot as plt
Hits= pd.read_excel("stackoverflow_example.xlsx", sheet_name="data")
fig=plt.figure(figsize=(20,10))
ax=fig.add_subplot(111, label="1")
ax2=fig.add_subplot(111, label="2", frame_on=False)
ax.bar(Hits['Date'], Hits['Total'], width=0.35, color="b" )
ax.set_ylabel('Hits', color="b",size=16)
ax.yaxis.set_label_position('right')
ax.tick_params(axis='y', colors="b")
ax.tick_params(axis='x', colors="b", rotation=45)
ax.yaxis.tick_right()
ax2.plot(Hits['weeks'], Hits['Cases'], linewidth= 3.5, color="Red")
ax2.set_ylabel("Cases", color="Red",size=16)
ax2.tick_params(axis='y', colors="Red", size=16)
ax2.xaxis.set_ticks_position('top')
major_ticks = np.arange(0, 10, 1)
ax.set_xticks(major_ticks)
ax.grid(which='major', alpha=0.5)
plt.show()
My data
[
Graph:

If you want to start from zero, you can do that with 'ax2.set_ylim()'. After that, you can specify the axes for the grid. If the color is black, you can set color='k'.
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(20,10))
ax=fig.add_subplot(111, label="1")
ax2=fig.add_subplot(111, label="2", frame_on=False)
ax.bar(Hits['Date'], Hits['Total'], width=0.35, color="b" )
ax.set_ylabel('Hits', color="b",size=16)
ax.yaxis.set_label_position('right')
ax.tick_params(axis='y', colors="b")
ax.tick_params(axis='x', colors="k", rotation=45)
ax.yaxis.tick_right()
ax2.plot(Hits['weeks'], Hits['Cases'], linewidth= 3.5, color="Red")
ax2.set_ylabel("Cases", color="Red",size=16)
ax2.tick_params(axis='y', colors="Red", size=16)
ax2.xaxis.set_ticks_position('top')
ax2.set_ylim(0,62) # update
major_ticks = np.arange(0, 10, 1)
ax.set_xticks(major_ticks)
ax.grid(which='major', axis='x', alpha=0.5) #update
ax2.grid(which='major', axis='y', alpha=0.5) # update
plt.show()

Related

Matplotlib - not showing background when plotting again same plot

I am plotting 4 subplots on 1 figure with code below. When I try to plot the same plot in the notebook later just with fig I receive the same plot but with no white background, it is transparent. Any idea why it happens and what should I do to also get white background in next plot?
fig, axes = plt.subplots(figsize=(14, 10), nrows=2, ncols=2)
vec1 = np.random.randint(1,11,100)
vec2 = np.random.rand(100)
vec3 = np.random.randn(100)
vec4 = np.random.random(100)
axes[0, 0].plot(vec1, label='1')
axes[0, 1].hist(vec2, bins=20, edgecolor='k')
axes[1, 0].plot(vec3, label='3')
axes[1, 1].hist(vec4, bins=20, edgecolor='k')
axes[0][0].set_title("randint", fontsize=15)
axes[0][1].set_title("rand", fontsize=15)
axes[1][0].set_title("randn", fontsize=15)
axes[1][1].set_title("random", fontsize=15)
fig.legend(loc='upper left')
fig.suptitle("Losowe wektory", fontsize=18)
fig.subplots_adjust(left=0.1, bottom=0.05, right=0.9, top=0.9, wspace=0.15, hspace=0.35)
fig, axes = plt.subplots(figsize=(14, 10), nrows=2, ncols=2, facecolor='white')
Setting facecolor to white solves the problem, first I thought it is would be basically white and we have to set transparency to get it but it is otherwise as I can see.

Putting two plots with different axes into one with Matplotlib

I have two plots in Matplotlib that I would like to merge. They have different axes and scales. Here is the code for each of them.
Electrical Power Plot:
#Case Study: Curtailment
from matplotlib import pyplot as plt
%matplotlib inline
load = [0, 250, 250, 250, 250, 250, 665, 2500, 2500, 2500, 2500, 2500,0,2500, 2366, 250, 250, 373, 2500,0, 2500, 0, 2500,250, 0]
hours = list(range(25)) # [0, 1, 2, ... 22, 23, 24]
labels = [f'{h:02d}:00' for h in hours] # ["00:00", "01:00", ... "23:00", "24:00"]
fig = plt.figure(linewidth=1, figsize=(9, 5))
ax = plt.gca()
ax.plot(hours, load, color="goldenrod",drawstyle="steps-post", linewidth=3) # <- drawstyle argument.
ax.set_xlabel("Time of day", fontsize=14, labelpad=8)
ax.set_ylabel("Electrical power in W", fontsize=14, labelpad=8)
ax.set_xlim(0, 24)
ax.set_ylim(0, 3000)
plt.xticks(hours, labels=labels, rotation=90)
plt.grid(axis='y', alpha=.4)
ax.tick_params(axis='both', which='major', labelsize=14)
# (Optional) ax.legend(loc='center left', bbox_to_anchor=(0.03, 1.15), fontsize = 14, ncol=3)
plt.tight_layout() # This must be called last, after all elements (plot and legend) are ready.
plt.savefig('CS_Curtailment_ElectricalLoad.png', edgecolor='black', dpi=400, bbox_inches='tight')
plt.show()
Temperature Plot:
#Case Study: Curtailment
from matplotlib import pyplot as plt
%matplotlib inline
temperature = [
21.00,
21.02,
20.96,
20.85,
20.68,
20.46,
20.40,
20.56,
20.77,
21.06,
21.41,
21.79,
21.10,
21.57,
22.00,
21.47,
20.92,
20.46,
20.92,
20.31,
20.77,
20.35,
20.90,
21.00,
21.00
]
hours = list(range(25)) # [0, 1, 2, ... 22, 23, 24]
labels = [f'{h:02d}:00' for h in hours] # ["00:00", "01:00", ... "23:00", "24:00"]
fig = plt.figure(linewidth=1, figsize=(9, 5))
ax = plt.gca()
ax.plot(hours, temperature, color="red", linewidth=3) # <- drawstyle argument.
ax.set_xlabel("Time of day", fontsize=14, labelpad=8)
ax.set_ylabel("Temperature in °C", fontsize=14, labelpad=8)
ax.set_xlim(0, 24)
ax.set_ylim(20, 22.5)
plt.xticks(hours, labels=labels, rotation=90)
plt.grid(axis='y', alpha=.4)
ax.tick_params(axis='both', which='major', labelsize=14)
# (Optional) ax.legend(loc='center left', bbox_to_anchor=(0.03, 1.15), fontsize = 14, ncol=3)
plt.tight_layout() # This must be called last, after all elements (plot and legend) are ready.
plt.savefig('CS_Curtailment_Temperature.png', edgecolor='black', dpi=400, bbox_inches='tight')
plt.show()
I would like to have the electrical power axis on the left (first plot) and the temperature axis on the right (second plot). Of course the two plots have similar x-axis values.
Can you do this with Matplotlib?
I'd appreciate every comment.
Yes this can be done in matplotlib to do so, first generate the first ax (electrical power) and then instantiate the second axes
ax.plot(hours, load, color="goldenrod",drawstyle="steps-post", linewidth=3)
# ...
#generate the second instance
ax2 = ax.twinx()
ax2.plot(hours, temperature, color="red", linewidth=3)
# ... set additional configuration for ax2
Both axes will share the same x-axes and the same fig, so make sure that before showing the plot to tight the layout, otherwise y-label might be clipped.
fig.tight_layout()
plt.show()
EDIT:
To handle both axes at the same time, you need to use the figure object, so use it to save them to a png and set the legend. legend() method need to receive the labels which you can set manually of on each ax.plot( ..., label='<label>')
get the current figure before plt.show()
Set the legend using the figure object.
Save the image using the figure object.
Show the image.
The code:
fig = plt.gcf()
fig.legend(loc='center left', bbox_to_anchor=(0.15, 1.07), fontsize=14, ncol=3)
fig.savefig('CS_Curtailment_CombinedDiagram.png',
edgecolor='black', dpi=400, bbox_inches='tight')
plt.show()

Color all tick labels in scientific notation

I want to color the tick labels of my left vertical axis. However, the following code:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1,5,10],[1,5,10])
ax.set_xscale('log')
ax.set_yscale('log')
ax.set_xlim([1e0,1e1])
ax.set_ylim([1e0,1e1])
ax.yaxis.label.set_color('b')
ax.spines['left'].set_edgecolor('b')
ax.tick_params(axis='y', colors='b')
plt.savefig('test.png')
plt.show()
fails to color all lables:
Use
ax.tick_params(axis='y', colors='b', which='both')
where both corresponds to the major as well as the minor ticks.
Output

How to move specific x-axis (minor) tick labels to the top of a figure in matplotlib?

I want to keep the major tick labels, that matplotlib has automatically generated, in their default position under the figure. However, I myself added some minor ticks (with vertical lines) at specific x values, but their labels don't fit between the default major ticks. How can I move these labels to the top of the figure?
My code for reference:
meta = comparisons['meta']
lagsAnycast = np.array(meta['lagsAnycast'])
lagsPenultimate = np.array(meta['lagsPenultimate'])
avgLagAnycast = meta['avgLagAnycast']
avgLagPenultimate = meta['avgLagPenultimate']
plt.step(lagsAnycast, (np.arange(lagsAnycast.size) + 1)/lagsAnycast.size, color='k', label='to anycast IPs', linewidth=1.5)
plt.step(lagsPenultimate, (np.arange(lagsPenultimate.size) + 1)/lagsPenultimate.size, color='k', label='to penultimate IPs', linewidth=1)
plt.axvline(round(avgLagAnycast,1), ls="dashed", color="k", label="average lag to anycast IPs", linewidth=1.5)
plt.axvline(round(avgLagPenultimate,1), ls="dashed", label="average lag to penultimate IPs", color="k", linewidth=1)
plt.axis([-0.34,60,0.7,1])
plt.xlabel("Lag (ms)")
plt.ylabel("CDF")
existingTicks = (plt.xticks())[0][1:].tolist()
plt.gca().xaxis.grid(True, which='major')
plt.gca().xaxis.grid(False, which='minor')
plt.gca().tick_params(axis="x", which="minor", direction="out", top=True)
plt.gca().set_xticks([round(avgLagAnycast,1), round(avgLagPenultimate,1)], minor=True)
plt.legend(loc='right', fontsize=10)
plt.grid(True, ls="dotted")
majorFormatter = FormatStrFormatter('%g')
plt.gca().xaxis.set_major_formatter(majorFormatter)
plt.savefig(os.path.join(os.getcwd(), "datasets/plots/CDF1.png"))
You can use Locators and Formatters to set the ticks and ticklabels and turn them on or off using tick_params:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
x = np.linspace(-3,3)
plt.plot(x, np.sin(x))
ticks = [-np.pi/2,np.pi/2.]
labels = [r"$-\frac{\pi}{2}$",r"$\frac{\pi}{2}$"]
ax = plt.gca()
ax.xaxis.set_minor_locator(ticker.FixedLocator(ticks))
ax.xaxis.set_minor_formatter(ticker.FixedFormatter(labels))
# Set visibility of ticks & tick labels
ax.tick_params(axis="x", which="minor", direction="out",
top=True, labeltop=True, bottom=False, labelbottom=False)
plt.show()

MatPlotLib Python 3.4: Enumerate and ax.annotate

I have constructed a horizontal bar chart as show with the code below.
Everything looks great except what are supposed to be annotated bars.
I can't figure out how to get the labels on the end of the bars and not in a table in the middle of the chart. Specifically, I'm looking at these lines of code:
for i, text in enumerate(ind):
ax.annotate(str(x_axis), (ind[i], x_axis[i]),fontsize=14, color='black', va='center', ha='center')
Here's the whole thing:
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
df0=pd.read_csv('sample1.csv')
fig, ax = plt.subplots(1, 1, figsize=(12,9))
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
x_axis = 8.6667, 9.5, -8.4, 0, -4, 6
y_axis = Hospital
y_axis = 'A','B','C','D','E','F'
ind = np.arange(len(y_axis))
plt.xticks(fontsize=12)
plt.yticks(ind, y_axis, fontsize=14)
plt.tick_params(
axis='x',
which='both',
top='off')
plt.tick_params(
axis='y',
which='both',
right='off',
left='off')
plt.title('Super Awesome Title', fontsize=18, ha='center')
#Label Bars: First is the older, simpler way but it has issues...
#for a, b in zip(ind, y_axis):
# plt.text(a, b, str(b), fontsize=16, color='black')
#Better, but more complex method:
for i, text in enumerate(ind):
ax.annotate(str(x_axis), (ind[i], x_axis[i]),fontsize=14, color='black', va='center', ha='center')
#Add padding around x_axis
plt.xlim([min(x_axis)-.5, max(x_axis)+.5])
#Add padding around y_axis
plt.ylim([min(ind)-.5, max(ind)+.5])
plt.barh(ind, x_axis, align='center', height=0.5, edgecolor='none', color='#AAA38E')
I just figured it out:
I had to switch ind and x_axis around and iterate over the x_axis:
ax.annotate(str(x_axis), (ind[i], x_axis[i])
should be:
ax.annotate(str(x_axis[i]), (x_axis[i], ind[i])

Categories