I want to:
A. See two y-axes (of two different graphs) with one x-axis.
B. See major gridlines for x-axis
c. See major and minor gridlines for y-axis of the primary plot
I can plot the graph perfectly with only one y-axis, BUT as soon as I uncomment "ax2 = ax1.twinx()", the minor gridlines of the primary axis disappear.
Picture: The correct format with single plot, and the minor_grid-problem with two plots.
Thank you in advance!
def plot_graph(x, y1, label1, y2, label2, title):
fig, ax1 = plt.subplots()
# Plotting y-axis 1
ax1.set_xlabel('Time (s)')
ax1.set_ylabel(label1, color = "red")
ax1.grid(which='major',axis='both', color='black', linewidth=1)
ax1.grid(which='minor',axis='y', color='gray', linewidth=0.3)
ax1.tick_params(axis = 'y')
ax1.plot(x, y1, color = "red")
# Plotting secondary y-axis with the same x-axis
ax2 = ax1.twinx() # PROBLEM: this alone hides the ax1 minor grid
ax2.set_ylabel(label2, color = 'blue')
ax2.plot(x,y2,color = 'blue')
ax2.tick_params(axis = 'y')
plt.minorticks_on()
plt.legend(loc='best')
plt.title(title)
plt.show()
return
Problem solved.
"plt.minorticks_on()" needs to be called before "ax2 = ax1.twinx()".
"axis='both'" in ax1.grid() does not work. => call separately for x and y axes.
'''
plot_graph(x, y1, label1, y2, label2, title):
fig, ax1 = plt.subplots()
#Plotting y-axis 1
ax1.set_xlabel('Time (s)')
ax1.set_ylabel(label1, color="red")
ax1.grid(which='major',axis='x', color='black', linewidth=1) # x major black
ax1.grid(which='minor',axis='x', color='gray', linewidth=0.3) # x minor gray
ax1.grid(which='major',axis='y', color = 'k', linewidth=1) # y major black
ax1.grid(which='minor',axis='y', color = 'gray',linewidth=0.3) # y minor gray (this was not showing)
ax1.plot(x, y1, color = "red")
plt.minorticks_on() # NEW PLACE - SOLUTION
#Plotting secondary y-axis with the same x-axis
ax2 = ax1.twinx()
ax2.set_ylabel(label2, color = 'blue')
ax2.plot(x,y2,color = 'blue')
ax2.tick_params(axis = 'y')
#plt.minorticks_on() # OLD PLACE
plt.legend(loc='best')
plt.title(title)
plt.show(block=False)
return
'''
Image: Correct output
The problem appears to be because of the axis='both' in the ax.grid lines. If you give it as both, it doesn't appear to like it and I am not sure why. I played around this appears to give what you need. Note that 3 of the grid lines are with ax1 and the other two are with ax2
Note:
I have some random numbers for x, y1, y2
I have given separate colors for X, y1/y2 major/minor lines so you
can see. Use the colors as you need.
Code
x = []
y1 = []
y2 = []
for i in range(0,10):
x.append(round(random.random()*160,2))
for i in range(0,10):
y1.append(round(random.random()*3000,2))
for i in range(0,10):
y2.append(round(random.random()*90,2))
fig, ax1 = plt.subplots()
# Plotting y-axis 1
ax1.set_xlabel('Time (s)')
ax1.set_ylabel('label1', color = "red")
ax1.grid(which='major', axis = 'x', color='g', linewidth=1) #Green Vertical major
ax1.grid(which='major', axis = 'y', color='m', linewidth=1) #Magenta Horizontal major
ax1.grid(which='minor', axis = 'x', color='y', linewidth=0.3) #Yellow Vertical minor
ax1.tick_params(axis = 'y')
ax1.plot(x, y1, color = "red")
# Plotting secondary y-axis with the same x-axis
ax2 = ax1.twinx() # PROBLEM STILL?
ax2.set_ylabel('label2', color = 'blue')
ax2.plot(x,y2,color = 'blue')
ax2.tick_params(axis = 'y')
ax2.grid(which='major', axis = 'y', color='k', linewidth=1) #Black Horizontal major
ax2.grid(which='minor', axis = 'y', color='grey', linewidth=0.3) #Grey Horizontal minor
plt.minorticks_on()
plt.legend(loc='best')
plt.title('title')
plt.show()
Graph
Related
plt.plot(x, y, label = name1)
plt.plot(x, y, label = name2)
plt.plot(x, y, label = name3)
plt.show()
How to get the label when I click the line or better if I can get this information directly in the graph window like I get the x and y axis values on bottom right.
The fastest way would be to add a legend to your graph with plt.legend() right before plt.show()
For more interactivity, maybe try bokeh instead of matplotlib.
Not sure exactly what you are asking for but if you want to represent each line with a name, or the series of the x-values, you could use legend() and input a string or series name as label name in the plot-line:
plt.plot(x1, y, label = "name1") # Show the string name1
plt.plot(x2, y, label = x2) # Shows the array x2
plt.legend() # Displays the legends
If you want to add title or labels for the axis you could use:
plt.xlabel('X-axis Label')
plt.ylabel('Y-axis label')
plt.title('Title')
I am not sure if this is what you are looking for? But you can easily name your graphs by using the Legend. the first graph will be the first in your Legendlist. The important code is between the slash :-)
import matplotlib.pyplot as plt
import numpy as np
# Select length of axes and the space between tick labels
xmin, xmax, ymin, ymax = -10, 10, -10, 10
ticks_frequency = 1
# Plot points
fig, ax = plt.subplots(figsize=(10, 10))
#//////////////////////////////////////////////////////////////////////////////
# x range
x = np.arange(-5, 5., 0.025)
# f1
y1 = 3*x+4
f1 = ax.plot(x, y1, lw = 3, alpha = 0.5, color="blue")
# f2
y2 = 1*x+1
f2 = ax.plot(x, y2, lw = 3, alpha = 0.5, color="orange")
# f3
y3 = -2*x+8
f3 = ax.plot(x, y3, lw = 3, alpha = 0.5, color="red")
# legend
ax.legend(["Gerade 1", "Gerade 2", "Gerade 3"])
#//////////////////////////////////////////////////////////////////////////////
# Set identical scales for both axes
ax.set(xlim=(xmin-1, xmax+1), ylim=(ymin-1, ymax+1), aspect='equal')
# Set bottom and left spines as x and y axes of coordinate system
ax.spines['bottom'].set_position('zero')
ax.spines['left'].set_position('zero')
# Remove top and right spines
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# Create 'x' and 'y' labels placed at the end of the axes
ax.set_xlabel('x', size=14, labelpad=-24, x=1.03)
ax.set_ylabel('y', size=14, labelpad=-21, y=1.02, rotation=0)
# Create custom major ticks to determine position of tick labels
x_ticks = np.arange(xmin, xmax+1, ticks_frequency)
y_ticks = np.arange(ymin, ymax+1, ticks_frequency)
ax.set_xticks(x_ticks[x_ticks != 0])
ax.set_yticks(y_ticks[y_ticks != 0])
# Create minor ticks placed at each integer to enable drawing of minor grid
# lines: note that this has no effect in this example with ticks_frequency=1
ax.set_xticks(np.arange(xmin, xmax+1), minor=True)
ax.set_yticks(np.arange(ymin, ymax+1), minor=True)
# Draw major and minor grid lines
ax.grid(which='both', color='grey', linewidth=1, linestyle='-', alpha=0.2)
# Draw arrows
arrow_fmt = dict(markersize=4, color='black', clip_on=False)
ax.plot((1), (0), marker='>', transform=ax.get_yaxis_transform(), **arrow_fmt)
ax.plot((0), (1), marker='^', transform=ax.get_xaxis_transform(), **arrow_fmt)
plt.show()
I would like to have an increasing spacing between legend items instead of a single value (labelspacing). The latter only accepts an int value type, but I want a variable spacing between legend items. Also, I want the markerfacecolor to follow the colormap used when creating the scatter plot.
N = 45
x, y = np.random.rand(2, N)
s = np.random.randint(10, 1000, size=N)
fig, ax = plt.subplots()
scatter = ax.scatter(x, y, c=s, s=s)
cbar = fig.colorbar(scatter,
ax=ax,
label='Size',
fraction=0.1,
pad=0.04)
# produce a legend with a cross section of sizes from the scatter
handles, labels = scatter.legend_elements(prop="sizes", alpha=0.6)
for hd in handles:
hd.set_markeredgewidth(2)
hd.set_markeredgecolor("red")
hd.set_markerfacecolor('blue')
legend2 = ax.legend(
handles[::2], labels[::2], loc="upper right", title="Sizes", labelspacing=1.2
)
plt.show()
I searched StackOverflow and tried some possible methods but without success. Could someone guide how I can achieve the desired output?
I managed to set markerfacecolor as the colormap. But I am still struggling with the variable labelspacing!.
Any help!
N = 45
x, y = np.random.rand(2, N)
s = np.random.randint(10, 1000, size=N)
fig, ax = plt.subplots()
scatter = ax.scatter(x, y, c=s, s=s)
cbar = fig.colorbar(scatter,
ax=ax,
label='Size',
fraction=0.1,
pad=0.04)
# produce a legend with a cross section of sizes from the scatter
handles, labels = scatter.legend_elements(prop="sizes", alpha=0.6)
leg_colrs = [color.get_markerfacecolor() for color in scatter.legend_elements()[0]]
for hd, color in zip(handles, leg_colrs):
hd.set_markeredgewidth(2)
hd.set_markeredgecolor("red")
hd.set_markerfacecolor(color)
legend2 = ax.legend(
handles[::2], labels[::2], loc="upper right", title="Sizes", labelspacing=1.2
)
plt.show()
I'm trying to plot some revenues against EBIT on a chart with a secondary Y-axis.
Everything seems to be ok except
the grid doesn't display entirely.
the x-axis doesn't display entirely either.
Does anyone have a solution to display entirely these 2 features ?
Here is a screen cap of my graph :
graph
Here is the data :
data
And here is my code :
x = msft_ebit_revenue_new['period']
y1 = msft_ebit_revenue_new['EBIT']
y2 = msft_ebit_revenue_new['Revenues']
Plot Line1 (Left Y Axis)
fig, ax1 = plt.subplots(1,1,figsize=(16,9), dpi= 80)
ax1.plot(x, y1, color='tab:red')
# Plot Line2 (Right Y Axis)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
ax2.plot(x, y2, color='tab:blue')
Decorations
ax1 (left Y axis)
ax1.set_xlabel('Period', fontsize=10)
ax1.tick_params(axis='x', rotation=0, labelsize=12)
ax1.set_ylabel('EBIT', color='tab:red', fontsize=20)
ax1.tick_params(axis='y', rotation=0, labelcolor='tab:red' )
ax1.grid(alpha=.4)
ax2 (right Y axis)
ax2.set_ylabel("Revenues ($ in millions)", color='tab:blue', fontsize=20)
ax2.tick_params(axis='y', labelcolor='tab:blue')
ax2.set_xticks(np.arange(0, len(x), 60))
ax2.set_xticklabels(x[::60], rotation=90, fontdict={'fontsize':10})
ax2.set_title("EBIT vs Revenues (MSFT)", fontsize=22)
fig.tight_layout()
plt.show()
Thank you !
Alex
Problem
Display x-axis labels
Display grid
Solution
Comment the following lines:
ax2.set_xticks(np.arange(0, len(x), 60))
ax2.set_xticklabels(x[::60], rotation=90, fontdict={'fontsize':10})
This is giving me major grid lines, as shown below.
How do I get one dark axis line for just y = 0?
fig, ax1 = subplots(figsize=(3,6))
ax1.yaxis.grid(True, linestyle='-', which='major', color='grey', alpha=0.5)
bound = 20
ylim([-bound,bound])
boxplot(data)
show()
You need a call to axhline:
axhline(0, color='black')
I am currently plotting the same data but visualizing it differently in two subplots (see figure):
Code snippet used for producing the above figure:
# Figure
plt.figure(figsize=(14,8), dpi=72)
plt.gcf().suptitle(r'Difference between TI and $\lambda$D', size=16)
# Subplot 1
ax1 = plt.subplot2grid((1,3),(0,0),colspan=2)
# Plot scattered data in first subplot
plt.scatter(LE_x, LE_y, s=40, lw=0, color='gold', marker='o', label=r'$\lambda$D')
plt.scatter(MD_x, MD_y, s=40, lw=0, color='blue', marker='^', label=r'TI')
# Subplot 2
ax2 = plt.subplot2grid((1,3),(0,2))
plt.barh(vpos1, LE_hist, height=4, color='gold', label=r'$\lambda$D')
plt.barh(vpos2, MD_hist, height=4, color='blue', label=r'TI')
# Legend
legend = plt.legend()
Is there any way to make the legend show both the scatter dots and the bars? Would this also go per dummy as described here? Could somebody then please post a minimal working example for this, since I'm not able to wrap my head around this.
This worked for me, you essentially capture the patch handles for each graph plotted and manually create a legend at the end.
import pylab as plt
import numpy as NP
plt.figure(figsize=(14,8), dpi=72)
plt.gcf().suptitle(r'Difference between TI and $\lambda$D', size=16)
# Subplot 1
ax1 = plt.subplot2grid((1,3),(0,0),colspan=2)
N = 100
LE_x = NP.random.rand(N)
LE_y = NP.random.rand(N)
MD_x = NP.random.rand(N)
MD_y = NP.random.rand(N)
# Plot scattered data in first subplot
s1 = plt.scatter(LE_x, LE_y, s=40, lw=0, color='gold', marker='o', label=r'$\lambda$D')
s2 = plt.scatter(MD_x, MD_y, s=40, lw=0, color='blue', marker='^', label=r'TI')
data = NP.random.randn(1000)
LE_hist, bins2 = NP.histogram(data, 50)
data = NP.random.randn(1000)
MD_hist, bins2 = NP.histogram(data, 50)
# Subplot 2
ax2 = plt.subplot2grid((1,3),(0,2))
vpos1 = NP.arange(0, len(LE_hist))
vpos2 = NP.arange(0, len(MD_hist)) + 0.5
h1 = plt.barh(vpos1, LE_hist, height=0.5, color='gold', label=r'$\lambda$D')
h2 = plt.barh(vpos2, MD_hist, height=0.5, color='blue', label=r'TI')
# Legend
#legend = plt.legend()
lgd = plt.legend((s1, s2, h1, h2), (r'$\lambda$D', r'TI', r'$\lambda$D', r'TI'), loc='upper center')
plt.show()