import numpy as np
import matplotlib.pyplot as plt
# Create some mock data
t = np.arange(0.01, 10.0, 0.01)
data1 = np.exp(t)
data2 = np.sin(2 * np.pi * t)
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel('time (s)')
ax1.set_ylabel('exp', color=color)
ax1.plot(t, data1, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx()
color = 'tab:blue'
ax2.set_ylabel('sin', color=color)
ax2.plot(t, data2, color=color)
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout()
plt.show()
enter image description here
I wonder if I could change the value on the x-axis. Thank you!!!
(The system forces me to type more words instead of code...)
Use set_xticklabels() with proper list of values.
ax2.set_xticklabels([1999,2000,2001,2002,2003,2004,2005])
Related
This site describes well how to draw two lines with different scales on the same plot.
However, the y ticks are not aligned as you can see in the following picture if I draw an horizontal grid across.
Is there a way to add ticks so that they align (e.g. the 5000 on the left is aligned with the 0.50 on the right, etc.)?
One could align the right ticks by setting their ylims to the corresponding ylims of the left:
ymin1, ymax1 = ax1.get_ylim()
ax2.set_ylim(ymin1 / 10000, ymax1 / 10000)
Or set the ylims of both axes to the widest range:
import numpy as np
import matplotlib.pyplot as plt
# Create some mock data
t = np.arange(0.01, 10.0, 0.01)
data1 = np.exp(t)
data2 = np.sin(2 * np.pi * t)
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel('time (s)')
ax1.set_ylabel('exp', color=color)
ax1.plot(t, data1, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
color = 'tab:blue'
ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1
ax2.plot(t, data2, color=color)
ax2.tick_params(axis='y', labelcolor=color)
ymin1, ymax1 = ax1.get_ylim()
ymin2, ymax2 = ax2.get_ylim()
ymin1 = min(ymin1, ymin2 * 10000)
ymax1 = max(ymax1, ymax2 * 10000)
ax1.set_ylim(ymin1, ymax1)
ax2.set_ylim(ymin1 / 10000, ymax1 / 10000)
ax1.grid(True, axis='y')
fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.show()
I use rcParams in one script to enlarge font size in figure with twin axis:
import numpy as np
import matplotlib.pyplot as plt
# Create some mock data
t = np.arange(0.01, 10.0, 0.01)
data1 = np.exp(t)
data2 = np.sin(2 * np.pi * t)
fig, ax1 = plt.subplots()
plt.rcParams.update({'axes.titlesize': 'large',
'axes.labelsize':'large',
'ytick.labelsize': 'large',
'xtick.labelsize': 'large'})
color = 'tab:red'
ax1.set_xlabel('time (s)')
ax1.set_ylabel('exp', color=color)
ax1.plot(t, data1, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
color = 'tab:blue'
ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1
ax2.plot(t, data2, color=color)
ax2.tick_params(axis='y', labelcolor=color)
plt.show()
But, plt.rcParams just works for one axis.
In this example, that is the blue ticks labels.
I want to enlarge all fonts size in the figure.
Is there any simple method to achieve it?
Your problem is that you are updating rcParams after you created the left axes (ax1)
move the line plt.rcParams.update(...) before fig, ax1 = plt.subplots()
I would like to display the following dataframe in barchart but with double y axis, I want to show areas columns on left side and prices columns on right side:
area1 area2 price1 price2
level
first 263.16 906.58 10443.32 35101.88
second 6879.83 14343.03 2077.79 4415.53
third 31942.75 60864.24 922.87 1774.47
I tried with code below, it works but only display left side.
import matplotlib.pyplot as plt
df.plot(kind='bar')
plt.xticks(rotation=45, fontproperties="SimHei")
plt.xlabel("")
plt.legend()
Thank you.
If I understood you correctly, one way could be this, but you have to "play" a bit with the values of width and position of the ticks:
import pandas as pd
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12,5))
ax = fig.add_subplot(111)
ax2 = ax.twinx()
width = 0.1
df.area1.plot(kind='bar', color='red', ax=ax, width=width, position=0 )
df.area2.plot(kind='bar', color='orange', ax=ax, width=width, position=1)
df.price1.plot(kind='bar', color='blue', ax=ax2, width=width, position=2)
df.price2.plot(kind='bar', color='green', ax=ax2, width=width, position=3)
ax.set_ylabel('Area')
ax2.set_ylabel('Price')
ax.legend(["Area1", "Area2"], bbox_to_anchor=(0.8,1.0))
ax2.legend(["Price1", "Price2"], bbox_to_anchor=(0.9,1.0))
plt.show()
Another way is this:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot(111)
ax2 = ax.twinx()
# ax.set_xticklabels(ax.get_xticklabels(),rotation=45) # Rotation 45 degrees
width = 0.1
ind = np.arange(len(df))
ax.set_ylabel('Area')
ax2.set_ylabel('Price')
ax.set_xlabel('Level')
ax.bar(ind, df.area1, width, color='red', label='area1')
ax.bar(ind + width, df.area2, width, color='orange', label='area2')
ax2.bar(ind + 2*width, df.price1, width, color='blue', label='price1')
ax2.bar(ind + 3*width, df.price2, width, color='green', label='price2')
ax.set(xticks=(ind + 1.5*width), xticklabels=df.index, xlim=[2*width - 1, len(df)])
ax.legend(["Area1", "Area2"], bbox_to_anchor=(1,1))
ax2.legend(["Price1", "Price2"], bbox_to_anchor=(1,0.87))
plt.show()
i wanted to know how to make a plot with two y-axis so that my plot that looks like this :
to something more like this by adding another y-axis :
i'm only using this line of code from my plot in order to get the top 10 EngineVersions from my data frame :
sns.countplot(x='EngineVersion', data=train, order=train.EngineVersion.value_counts().iloc[:10].index);
I think you are looking for something like:
import matplotlib.pyplot as plt
x = [1,2,3,4,5]
y = [1000,2000,500,8000,3000]
y1 = [1050,3000,2000,4000,6000]
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.bar(x, y)
ax2.plot(x, y1, 'o-', color="red" )
ax1.set_xlabel('X data')
ax1.set_ylabel('Counts', color='g')
ax2.set_ylabel('Detection Rates', color='b')
plt.show()
Output:
#gdubs If you want to do this with Seaborn's library, this code set up worked for me. Instead of setting the ax assignment "outside" of the plot function in matplotlib, you do it "inside" of the plot function in Seaborn, where ax is the variable that stores the plot.
import seaborn as sns # Calls in seaborn
# These lines generate the data to be plotted
x = [1,2,3,4,5]
y = [1000,2000,500,8000,3000]
y1 = [1050,3000,2000,4000,6000]
fig, ax1 = plt.subplots() # initializes figure and plots
ax2 = ax1.twinx() # applies twinx to ax2, which is the second y axis.
sns.barplot(x = x, y = y, ax = ax1, color = 'blue') # plots the first set of data, and sets it to ax1.
sns.lineplot(x = x, y = y1, marker = 'o', color = 'red', ax = ax2) # plots the second set, and sets to ax2.
# these lines add the annotations for the plot.
ax1.set_xlabel('X data')
ax1.set_ylabel('Counts', color='g')
ax2.set_ylabel('Detection Rates', color='b')
plt.show(); # shows the plot.
Output:
Seaborn output example
You could try this code to obtain a very similar image to what you originally wanted.
import seaborn as sb
from matplotlib.lines import Line2D
from matplotlib.patches import Rectangle
x = ['1.1','1.2','1.2.1','2.0','2.1(beta)']
y = [1000,2000,500,8000,3000]
y1 = [3,4,1,8,5]
g = sb.barplot(x=x, y=y, color='blue')
g2 = sb.lineplot(x=range(len(x)), y=y1, color='orange', marker='o', ax=g.axes.twinx())
g.set_xticklabels(g.get_xticklabels(), rotation=-30)
g.set_xlabel('EngineVersion')
g.set_ylabel('Counts')
g2.set_ylabel('Detections rate')
g.legend(handles=[Rectangle((0,0), 0, 0, color='blue', label='Nontouch device counts'), Line2D([], [], marker='o', color='orange', label='Detections rate for nontouch devices')], loc=(1.1,0.8))
When i try plot the following data in python, i do not see the green color portion in my graph. Please find it below. Meanwhile, please be noted that I use python 2.7.4.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
%matplotlib inline
range = pd.date_range('2015-01-01', '2015-12-31', freq='15min')
df = pd.DataFrame(index = range)
df
# Average speed in miles per hour
df['speed'] = np.random.randint(low=0, high=60, size=len(df.index))
# Distance in miles (speed * 0.5 hours)
df['distance'] = df['speed'] * 0.25
# Cumulative distance travelled
df['cumulative_distance'] = df.distance.cumsum()
df.head()
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(df.index, df['speed'], 'g-')
ax2.plot(df.index, df['distance'], 'b-')
ax1.set_xlabel('Date')
ax1.set_ylabel('Speed', color='g')
ax2.set_ylabel('Distance', color='b')
plt.show()
plt.rcParams['figure.figsize'] = 12,5
Speed and distance are two parameters which are directly proportional to each other. If you normalize speed/distance sets, you get exactly the same graph. As you draw your drafts with alpha=1 (opaque), then the only color you see is the last one drawn (blue). If you use alpha <> 1:
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(df.index, df['speed'], 'g-', alpha=0.5)
ax2.plot(df.index, df['distance'], 'b-', alpha=0.1)
ax1.set_xlabel('Date')
ax2.set_ylabel('Distance', color='b')
ax1.set_ylabel('Speed', color='g')
plt.show()
plt.rcParams['figure.figsize'] = 12,5
you see the green color (in fact a mixture of green and blue):