How to get Major and Minor Tick Labels - python

I have the output of a group-by representing a sum of dates per week.
Date
2008-10-28 20.0
2008-11-04 25.0
2008-11-11 20.0
2008-11-18 40.0
2008-11-25 35.0
2008-12-02 35.0
2008-12-09 NaN
2008-12-16 NaN
2008-12-23 NaN
2008-12-30 NaN
Freq: W-TUE, Name: Count, dtype: float64
I'm trying to plot these using plot_date
fig, ax = plt.subplots(figsize=(2, 4))
# ax = plt.gca()
line = ax.plot_date(a.index, a.values, '.', label='a', alpha=0.5, linewidth=1)
ax.tick_params('y', colors='k')
ax.set_xlabel('Date')
ax.set_ylabel('Frequency')
ax.set_title('Daily Games')
ax.tick_params('y', colors='k')
ax.grid(b=True, which='major', color='w', linewidth=1.0)
ax.grid(b=True, which='minor', color='w', linewidth=0.5)
ax.yaxis.grid(True)
ax.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())
ax.set_xticklabels(ax.xaxis.get_majorticklabels(),
rotation=70)
ax.set_xticklabels(ax.xaxis.get_minorticklabels(),
rotation=70)
plt.xticks(rotation=70)
plt.show()
This is producing a graph like so:
I've tried all manner of rearranging but I can't get both minor and major labels for the date to plot.
I'd like to have each month labelled at 70 degrees. How can I adjust what I have to do so?

You could use the AutoDateLocator() as follows:
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
sns.set()
a = pd.DataFrame([
('2008-10-28', 20.0), ('2008-11-04', 25.0), ('2008-11-11', 20.0),
('2008-11-18', 40.0), ('2008-11-25', 35.0), ('2008-12-02', 35.0)], columns=['Date', 'Frequency'])
a['Date'] = pd.to_datetime(a['Date'], format='%Y-%m-%d')
fig, ax = plt.subplots(figsize=(5, 5))
# ax = plt.gca()
line = ax.plot_date(a.Date, a.Frequency, '.', label='a', alpha=0.5, linewidth=1)
ax.tick_params('y', colors='k')
ax.set_xlabel('Date')
ax.set_ylabel('Frequency')
ax.set_title('Daily Games')
ax.tick_params('y', colors='k')
ax.grid(b=True, which='major', color='w', linewidth=1.0)
ax.grid(b=True, which='minor', color='w', linewidth=0.5)
ax.yaxis.grid(True)
xtick_locator = mpl.dates.AutoDateLocator()
xtick_formatter = mpl.dates.AutoDateFormatter(xtick_locator)
ax.xaxis.set_major_locator(xtick_locator)
ax.xaxis.set_major_formatter(xtick_formatter)
fig.subplots_adjust(bottom=0.24)
plt.xticks(rotation=70)
plt.show()
This would then display as:

From #MartinEvans suggestion to use AutoDateLocator() I looked up more of the matplotlib documentation and found matplotlib.dates.MonthLocator along with the WeekdayLocator. This allowed tuning the major and minor xticks to change the format and appearance as required.
I then used this answer to set their rotation.
fig, ax = plt.subplots(figsize=(2, 4))
# ax = plt.gca()
line = ax.plot_date(a.Date, a.Frequency, '.', label='a', alpha=0.5, linewidth=1)
ax.tick_params('y', colors='k')
# ax.xticks(rotation=70)
ax.set_xlabel('Date')
# ax.xlabel('Date')
ax.set_ylabel('Frequency')
ax.set_title('Daily Games')
ax.tick_params('y', colors='k')
ax.grid(b=True, which='major', color='w', linewidth=1.0)
ax.grid(b=True, which='minor', color='w', linewidth=0.5)
ax.yaxis.grid(True)
xtick_locator = mpl.dates.MonthLocator(interval=1)
xtick_formatter = mpl.dates.AutoDateFormatter(xtick_locator)
ax.xaxis.set_major_locator(xtick_locator)
ax.xaxis.set_major_formatter(xtick_formatter)
xtick_locator = mpl.dates.WeekdayLocator(byweekday=3)
xtick_formatter = mpl.dates.AutoDateFormatter(xtick_locator)
ax.xaxis.set_minor_locator(xtick_locator)
ax.xaxis.set_minor_formatter(xtick_formatter)
plt.setp(ax.xaxis.get_minorticklabels(), rotation=90, size=10)
plt.setp(ax.xaxis.get_majorticklabels(), rotation=90, size=7)
fig.subplots_adjust(bottom=0.24)
plt.show()

Related

Legend in subplots() for vertical lines Matplotlib.pyplot Python

I am trying to do EDA with the Kaggle dataset link
I made a plot with 3 subplots and have plotted 3 vertical lines on the basis of mean, median and mode. is there any way to show these 3 lines in a legend?
This is my code
def plott(data):
fig, axes = plt.subplots(3, sharex=True, figsize=(15, 15),gridspec_kw={"height_ratios": (1, 0.2, 0.6)})
fig.suptitle('Spread of Data for ' + data.name, fontsize=20, fontweight='bold')
sns.histplot(data, kde=True, binwidth=1, ax=axes[0])
sns.boxplot(x=data, orient='h', ax=axes[1])
sns.violinplot(x=data, ax=axes[2])
axes[0].set_xlabel('')
axes[1].set_xlabel('')
axes[2].set_xlabel('')
axes[0].axvline(data.mean(), color='r', linewidth=2, linestyle='solid')
axes[0].axvline(data.median(), color='r', linewidth=2, linestyle='dashed')
axes[0].axvline(data.mode()[0], color='r', linewidth=2, linestyle='dotted')
axes[1].axvline(data.mean(), color='r', linewidth=2, linestyle='solid')
axes[1].axvline(data.median(), color='r', linewidth=2, linestyle='dashed')
axes[1].axvline(data.mode()[0], color='r', linewidth=2, linestyle='dotted')
axes[2].axvline(data.mean(), color='r', linewidth=2, linestyle='solid')
axes[2].axvline(data.median(), color='r', linewidth=2, linestyle='dashed')
axes[2].axvline(data.mode()[0], color='r', linewidth=2, linestyle='dotted')
axes[0].tick_params(axis='both', which='both', labelsize=10, labelbottom=True)
axes[1].tick_params(axis='both', which='both', labelsize=10, labelbottom=True)
axes[2].tick_params(axis='both', which='both', labelsize=10, labelbottom=True)
plott(df['Age'])
This is the resulting plot
Is there a way to add the legend in here in accordance to the 3 vertical lines
like this with each line type denoting the value?
Also, how to add more values in x axis of all three graphs?
like make it interval of 5 or 2 years apart?
Thanks
Give the axvlines a "label" value, then call plt.legend after plotting it.
Example:
import matplotlib.pyplot as plt
plt.plot([1,2,3],[1,2,3],label="Test")
plt.axvline(x=0.22058956, label="Test2", color="red")
plt.legend()
Output:

Write a Circumflex Larger in Python

I can write 'A circumflex' as a label on a graph in Python:
df = pd.DataFrame({'x':(0,3,4,0),'y':(3,0,4,3)})
fig, ax = plt.subplots(1,1)
df.plot(x='x', y='y', ax=ax, label='A\u0302', linewidth=5, color='k', linestyle='-')
for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
ax.get_xticklabels() + ax.get_yticklabels()):
item.set_fontsize(22)
legend = ax.legend(loc=0, ncol=1, bbox_to_anchor=(0.9, -.3, .6, 1),
fancybox=True, shadow=False,
framealpha=1, fontsize=22)
plt.setp(legend.get_title(),fontsize=22)
This gives:
How can I get the circumflex larger please?
Thanks to Mr. T & tmdavison, either $^{A}$ or $\hat{A}$ work for some reason:
df = pd.DataFrame({'x':(0,3,4,0),'y':(3,0,4,3)})
fig, ax = plt.subplots(1,1)
df.plot(x='x', y='y', ax=ax, label='$A\u0302$', linewidth=5, color='k', linestyle='-')
df.plot(x='x', y='y', ax=ax, label='$\^{A}$', linewidth=5, color='k', linestyle='-')
df.plot(x='x', y='y', ax=ax, label='$\hat{A}$', linewidth=5, color='k', linestyle='-')
for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
ax.get_xticklabels() + ax.get_yticklabels()):
item.set_fontsize(22)
legend = ax.legend(loc=0, ncol=1, bbox_to_anchor=(0.9, -.3, .6, 1),
fancybox=True, shadow=False,
framealpha=1, fontsize=22)
plt.setp(legend.get_title(),fontsize=22)

X-axis minor gridlines still not showing even after trying all solutions

My x-axis minor gridlines are not showing, this is my code
ax = plt.gca()
ax.minorticks_on()
plt.semilogx(data_x1,data_y1,"red")
plt.semilogx(data_x2,data_y2,"blue")
ax.grid(b=True, which='major',axis="both", color='k', linestyle='-', linewidth=0.5)
ax.grid(b=True, which='minor',axis="both", color='k', linestyle='-', linewidth=0.2)
plt.xlabel("frequency(Hz)")
plt.ylabel("Iramp(dB)")
plt.show()
enter image description here
Either I'm not sure of what you want, or your code is actually working correctly. The minor grid lines are those between the powers of 10. I made a little example to show a comparison of your plot with the minor grid lines on and off.
import numpy as np
import matplotlib.pyplot as plt
data_x1 = np.linspace(0,2,10)
data_x2 = np.linspace(0,4,10)
data_y1 = np.random.rand(10)
data_y2 = np.random.rand(10)
fig, axall =plt.subplots(1,2, figsize=(10,5))
# your code with some changes
ax = axall[0]
ax.minorticks_on()
ax.semilogx(data_x1,data_y1,"red")
ax.semilogx(data_x2,data_y2,"blue")
ax.grid(b=True, which='major',axis="both", color='k', linestyle='-', linewidth=0.5)
ax.grid(b=True, which='minor',axis="both", color='k', linestyle='-', linewidth=0.2)
ax.set_xlabel("frequency(Hz)")
ax.set_ylabel("Iramp(dB)")
# code to make the plot on the right.
ax = axall[1]
ax.minorticks_on()
ax.semilogx(data_x1,data_y1,"red")
ax.semilogx(data_x2,data_y2,"blue")
ax.grid(b=True, which='major',axis="both", color='k', linestyle='-', linewidth=0.5)
# ax.grid(b=True, which='minor',axis="both", color='k', linestyle='-', linewidth=0.2)
ax.set_xlabel("frequency(Hz)")
ax.set_ylabel("Iramp(dB)")
plt.show()
Note how I commented out your minor grid lines.

Seaborn Heatmap Behavior

Consider this code:
fig, ax = plt.subplots(figsize=(8,5))
sns.heatmap(np.ones((4,4)), ax=ax, cbar=None, cmap="Blues", linewidths=1, linecolor='black')
fig, ax = plt.subplots(figsize=(8,5))
sns.heatmap(np.ones((4,4)), ax=ax, cmap="Blues", linewidths=1, linecolor='black')
It outputs:
Why does adding the argument cbar=None change the result of the outcome?
It is the default behavior by cbar, some kind of bug.
Turn off cbar:
fig, ax = plt.subplots(figsize=(8,5))
sns.heatmap(np.ones((4, 4)), ax=ax, cmap='Blues', linewidths=1, linecolor='black', cbar=False, vmin=0, vmax=2)
Turn on cbar:
fig, ax = plt.subplots(figsize=(8,5))
sns.heatmap(np.ones((4,4)), ax=ax, cmap='Blues', linewidths=1, linecolor='black', cbar=True, vmin=0, vmax=2)
As showed by #Alpha, cbar value should be boolean as it can be seen in the documentation
cbar : boolean, optional
Whether to draw a colorbar.
For both figures to have the same size, you can use:
fig, ax = plt.subplots(figsize=(8,5))
sns.heatmap(np.ones((4,4)), ax=ax, linewidths=1, linecolor='black', cmap="Blues",)
cbar = ax.collections[0].colorbar
cbar.remove()
plt.show()
and ...
fig, ax = plt.subplots(figsize=(8,5))
sns.heatmap(np.ones((4,4)), ax=ax, linewidths=1, linecolor='black', cmap="Blues",)
cbar = ax.collections[0].colorbar
#cbar.remove()
plt.show()

Assign figure to correct subplot

I have a set of subplot's that display different information. For the example below, I can assign the scatter plot to the designated subplot but the two distplot occupy the last subplot created.
import matplotlib.pyplot as plt
import seaborn as sns
x = [1,4,5,6,7,8]
x2 = [3,4,8,2,8,8]
y = [1,2,4,8,1,9]
def L_plot(ax, fontsize=12):
ax.set_xlabel('x-label', fontsize=8)
ax.set_ylabel('y-label', fontsize=8)
ax.set_title('L', fontsize=10)
ax.grid(False)
ax.scatter(x, y)
def E_plot(ax2,pid, fontsize=12):
ax2.set_xlabel('x-label', fontsize=8)
ax2.set_ylabel('y-label', fontsize=8)
ax2.set_title('E', fontsize=10)
ax2.grid(False)
ax2 = sns.distplot(x, kde=False, norm_hist=True, color='b', bins = 10)
def D_plot(ax,pid, fontsize=12):
ax.set_xlabel('x-label', fontsize=8)
ax.set_ylabel('y-label', fontsize=8)
ax.set_title('D', fontsize=10)
ax.grid(False)
ax = sns.distplot(x2, kde=False, norm_hist=True, color='b', bins = 10)
ax1 = plt.subplot2grid((3,1), (0, 0))
ax2 = plt.subplot2grid((3,1), (1, 0))
ax3 = plt.subplot2grid((3,1), (2, 0))
L_plot(ax1,1)
E_plot(ax2,1)
D_plot(ax3,1)
plt.tight_layout()
plt.show()
I'm trying to assign E_plot to the subplot in the second row but both distplot's are located in the last subplot created.
I'm not sure if the seaboard packages can't be assigned or I'm not correctly assigning it?
The call signature for distplot is:
seaborn.distplot(a, bins=None, hist=True, kde=True, rug=False,
fit=None, hist_kws=None, kde_kws=None, rug_kws=None,
fit_kws=None, color=None, vertical=False,
norm_hist=False, axlabel=None, label=None,
ax=None)
Notice the last option. If you don't tell it which Axes object to use, it'll use the one returned by pyplot.gca() (gca = "get current Axes").
So you need to do, e.g.,
sns.distplot(x2, kde=False, norm_hist=True, color='b', bins=10, ax=ax2)

Categories

Resources