Related
I'm trying to create a plot with 4 hist2d subplots and one color bar.
The thing is that each subplot can have different ranges of z values, so the color bar is not uniform.
I want to set the color bar to a pre-defined range.
here is the code I'm using:
def multiple_med_plot_test(file):
extent = [-8, 37, 28, 46]
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(26, 11), constrained_layout=True,
subplot_kw={'projection': ccrs.PlateCarree()})
ax0 = axes[0][0]
ax1 = axes[0][1]
ax2 = axes[1][0]
ax3 = axes[1][1]
axes_dict = {'Dec': ax0, 'Aug': ax1, 'Sep': ax2, 'Sum': ax3}
for month in axes_dict.keys():
ax = axes_dict[month]
ax.add_feature(cfeature.LAND, edgecolor='k', zorder=50)
ax.set_extent(extent)
gl = ax.gridlines(draw_labels=True, zorder=100, color='grey', linestyle='--')
gl.top_labels = False
gl.right_labels = False
gl.xlabel_style = {'size': 16}
gl.ylabel_style = {'size': 16}
if ax in [ax1, ax3]:
gl.left_labels = False
ax.set_title(month, fontsize=18, color='darkred')
if month != 'Sum':
hist0 = ax.hist2d(file.Long, file.Lat, range=[(-8, 37), (28, 46)], bins=(500, 200))
elif month == 'Sum':
hist1 = ax.hist2d(file.Long, file.Lat, range=[(-8, 37), (28, 46)], bins=(500, 200))
fig.suptitle('Lightning Density per Month', fontsize=22)
cbar = fig.colorbar(hist1[3], ax=axes, shrink=0.95)
cbar.set_label('# of lightnings', fontsize=20, rotation=-90, labelpad=30)
cbar.ax.tick_params(labelsize=16)
# plt.savefig('D:/Lightning Data/Yearly_Summary', dpi=100)
plt.show()
In previous versions of the code I used plt.clim and that was awesome, but the way my code is right now doesn't let me do it.
I would like to get some help on this!
If you want a linear scale, set vmin and vmax parameters. For log-like scale or similar, use norm. See hist2d documentation.
I'm plotting a pie chart using the following code:
fig1, ax1 = plt.subplots(figsize=(8,12))
ax1.pie(data,
labels=label,
radius=1,
startangle=90,
colors=cols,
counterclock=False,
shadow=False,
wedgeprops={'edgecolor': 'white', 'linewidth': 1},
textprops={'fontsize': 8},
pctdistance=0.85,
autopct='%1.1f%%')
plt.title('Title', fontsize=16)
plt.tight_layout()
When I change the font size in textprops both the font size of the labels and the percentages change.
What I would like to do is use different font sizes for the labels and the percentages.
I applied your code to the example in the official reference and added the code to change the font.
import matplotlib.pyplot as plt
# Pie chart, where the slices will be ordered and plotted counter-clockwise:
l = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')
cols = ['C0','C1','C2','C3']
fig1, ax1 = plt.subplots(figsize=(8,12))
wdges, labels, autopct = ax1.pie(sizes,
labels=l,
radius=1,
startangle=90,
colors=cols,
counterclock=False,
shadow=False,
wedgeprops={'edgecolor': 'white', 'linewidth': 1},
textprops={'fontsize': 8},
pctdistance=0.85,
autopct='%1.1f%%')
plt.setp(labels, fontsize=15) #update
plt.title('Title', fontsize=16)
plt.tight_layout()
I am trying to make a combined graph for one of my systems. I am trying to visualize time series data using bar chart along with line chart(with step).
This is a time series data therefore, I want to show datetime in the x label.
When I plot bar chart with df2['datetime'].index I get plots as expected but I do not get datetime as x-ticks. I believe that this is because I am using df2['datetime'].index.
When I plot bar chart with df2['datetime'] I get datetime in x-ticks however, the plot does not look realistic.
I am also attaching a snapshot of my data for better understanding. Any suggestions will be useful. Thank you.
fig,(ax0,ax1) = plt.subplots(1,2, figsize = (24,12))
ax0.bar(df2['datetime'].index, df2['T1'], width = 1, color='blue', align = 'edge', alpha = 0.5, label ='T1')
ax0.bar(df2['datetime'].index, -1*df2['T2'], width = 1, color='red', align = 'edge',alpha = 0.5, label ='T2')
ax0.step(df2['datetime'].index, df2['T3'], color='blue', linewidth=2, where = 'post', label ='T3')
ax0.step(df2['datetime'].index, -1*df2['T4'], color='red', linewidth=2, where = 'post', label ='T4')
ax00 = ax0.twinx()
ax00.step(df2['datetime'].index, df2['A1'], color='b', linestyle = '--', linewidth=1, where = 'post', label ='A1')
ax00.step(df2['datetime'].index, df2['A2'], color='r', linestyle = '--', linewidth=1, where = 'post', label ='A2')
ax00.set_ylabel('L2', fontsize=12, color='black')
ax0.set_ylabel("L1", fontsize=12, color='black')
ax0.set_xlabel("Datetime", fontsize=12, color='black')
ax0.set_title('Zone 2', fontsize=16, color='black')
ax0.grid(True)
ax0.legend(loc='upper left',fontsize = 12)
ax00.legend(loc='upper right',fontsize = 12)
ax1.bar(df2['datetime'], df2['T1'], width = 1, color='blue', align = 'edge', alpha = 0.5, label ='T1')
ax1.bar(df2['datetime'], -1*df2['T2'], width = 1, color='red', align = 'edge',alpha = 0.5, label ='T2')
ax1.step(df2['datetime'], df2['T3'], color='blue', linewidth=2, where = 'post', label ='T3')
ax1.step(df2['datetime'], -1*df2['T4'], color='red', linewidth=2, where = 'post', label ='T4')
ax01 = ax1.twinx()
ax01.step(df2['datetime'], df2['A1'], color='b', linestyle = '--', linewidth=1, where = 'post', label ='A1')
ax01.step(df2['datetime'], df2['A2'], color='r', linestyle = '--', linewidth=1, where = 'post', label ='A2')
ax01.set_ylabel('L2', fontsize=12, color='black')
ax1.set_ylabel("L1", fontsize=12, color='black')
ax1.set_xlabel("Datetime", fontsize=12, color='black')
ax1.set_title('Zone 1', fontsize=16, color='black')
ax1.grid(True)
ax1.legend(loc='upper left',fontsize = 12)[![enter image description here][1]][1]
ax01.legend(loc='upper right',fontsize = 12)
plt.show()
The problem probably comes from width = 1, because using datetime, a width of 1 is not equal to the size between two datapoints.
Try to use a smaller width in
ax1.bar(df2['datetime'], df2['T1'], width = 1, color='blue', align = 'edge', alpha = 0.5, label ='T1')
ax1.bar(df2['datetime'], -1*df2['T2'], width = 1, color='red', align = 'edge',alpha = 0.5, label ='T2')
You can also compute what exact width you need, but I'll let you search how to do that ;)
I have a program that is analyzing a dataset from a pandas dataframe.
The following is part of the program and it works perfectly:
selected_columns = ['cap-color', 'gill-color', 'veil-color', 'spore-print-color']
for col in selected_columns:
x = X[col].value_counts()
x_vals = x.values.tolist()
cap_color_list = ['brown', 'gray', 'red', 'yellow', 'white', 'buff', 'pink', 'cinnamon', 'green', 'purple']
gill_color_list = ['buff', 'pink', 'white', 'brown', 'gray', 'chocolate', 'purple', 'black', 'red', 'yellow', 'orange', 'green']
veil_color_list = ['white', 'brown', 'orange', 'yellow']
spore_print_color_list = ['white', 'brown', 'black', 'chocolate', 'green', 'purple', 'orange', 'buff', 'yellow']
plt.figure(figsize=(8, 6), facecolor='0.9')
x.plot(kind='bar', width=0.7, color='lightgreen', edgecolor='darkgreen')
if col == 'cap-color':
plt.xticks([i for i in range(len(x))], cap_color_list, rotation=0)
plt.title('cap-color', fontsize=15, color='darkred', weight='bold')
if col == 'gill-color':
plt.xticks([i for i in range(len(x))], gill_color_list, rotation=0)
plt.title('gill-color', fontsize=15, color='darkred', weight='bold')
if col == 'veil-color':
plt.xticks([i for i in range(len(x))], veil_color_list, rotation=0)
plt.title('veil-color', fontsize=15, color='darkred', weight='bold')
if col == 'spore-print-color':
plt.xticks([i for i in range(len(x))], spore_print_color_list, rotation=0)
plt.title('spore-print-color', fontsize=15, color='darkred', weight='bold')
for i, number in enumerate(x_vals):
plt.text(x=i, y=number, s=str(number), horizontalalignment='center', fontsize=10, weight='bold')
plt.xlabel("Color", size=16, labelpad=8, color='darkred')
plt.ylabel("Count", size=16, labelpad=8, color='darkred')
plt.show()
Sample output (just one, not all four):
Note how the light grey face color is applied.
Later in the program I have this block of code:
# plt.clf()
plt.figure(figsize=(8, 6), facecolor='0.9')
TEMP.plot(kind='bar', width=0.9)
for i, number in enumerate(TEMP['e']):
plt.text(x=i - 0.25, y=number + 0.9, horizontalalignment='center', s=round(number, 2), fontsize=8, weight='bold')
for i, number in enumerate(TEMP['p']):
plt.text(x=i + 0.22, y=number + 0.9, horizontalalignment='center', s=round(number, 2), fontsize=8, weight='bold')
plt.xticks([i for i in range(6)], population, rotation=0)
plt.title('Population', fontsize=15, color='darkred', weight='bold')
# plt.ylim(top=3000)
plt.xlabel("Population Type", size=16, labelpad=8, color='darkred')
plt.ylabel("Count", size=16, labelpad=8, color='darkred')
plt.show()
I get this result:
This entire line does nothing:
plt.figure(figsize=(8, 6), facecolor='0.9')
No matter what I change the figsize values to, nothing changes. The facecolor='0.9' is also
not being applied.
Everything else about the second bar chart is correct.
Why am I unable to control the figsize and facecolor in the second bar chart?
The second bar chart is being created from this temp df:
print('*' * 26)
TEMP = df.groupby('class')['population'].value_counts().unstack(level=1).fillna(0).T.sort_values('e', ascending=False)
TEMP = TEMP.astype(int)
print(TEMP)
print('*' * 26, '\n')
Output:
**************************
class e p
population
v 1192 2848
y 1064 648
s 880 368
n 400 0
a 384 0
c 288 52
**************************
pandas.DataFrame.plot returns an Axes, and has a figsize parameter.
This option won't work if facecolor is used as a parameter inside the DataFrame.plot
ax = x.plot(kind='bar', width=0.7, color='lightgreen', edgecolor='darkgreen', figsize=(8, 6))
ax = TEMP.plot(kind='bar', width=0.9, figsize=(8, 6))
If facecolor is required, use this implementation.
fig, axe = plt.subplots(figsize=(8, 6), facecolor='0.9')
x.plot(kind='bar', width=0.7, color='lightgreen', edgecolor='darkgreen', ax=axe)
fig, axe = plt.subplots(figsize=(8, 6), facecolor='0.9')
TEMP.plot(kind='bar', width=0.9, ax=axe)
When plotting with twinx how can multiple subplots be used?
%pylab inline
import pandas as pd
import seaborn as sns; sns.set()
df = pd.DataFrame({'dt':['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04'], 'category':['a', 'b', 'a', 'b'], 'foo':[10, 15, 8, 13], 'bar':[12, 8, 5, 18]})
df['dt'] = pd.to_datetime(df['dt'])
ax = sns.lineplot(x='dt', y='foo', data=df, hue='category')
ax.set_ylabel('asdf', fontsize=28)
ax.plot([], '-g', label = 'other axis in legend')
plt.legend(fontsize='x-large')
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles=handles[1:], labels=labels[1:], fontsize='large', loc='lower left')
plt.xticks(rotation=90, horizontalalignment='center', fontsize=28)
plt.xlabel('')
plt.yticks(fontsize=16)
ax2 = ax.twinx()
ax2 = sns.lineplot(x='dt', y='bar', data=df, ax=ax2, color='green')
plt.yticks(fontsize=16)
ax2.plot([], '-g', label = 'other axis in legend')
ax2.set_ylabel('ratio', fontsize=28)
plt.axvline(x=np.datetime64('2020-01-02'),color='k', linestyle='--', lw=4)
plt.text(x=np.datetime64('2020-01-02'), y=10, s=' foo-the-bar ', fontsize=28, horizontalalignment='left')
plt.show()
d2 = pd.DataFrame({'dt':['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04'], 'category':['a', 'b', 'a', 'b'],'foo':[11, 16, 8, 14], 'bar':[11, 7, 4, 17]})
d2['dt'] = pd.to_datetime(d2['dt'])
ax = sns.lineplot(x='dt', y='foo', data=d2, hue='category')
ax.set_ylabel('something else', fontsize=28)
ax.plot([], '-g', label = 'other axis in legend')
plt.legend(fontsize='x-large')
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles=handles[1:], labels=labels[1:], fontsize='large', loc='lower left')
plt.xticks(rotation=90, horizontalalignment='center', fontsize=28)
plt.xlabel('')
plt.yticks(fontsize=16)
plt.axvline(x=np.datetime64('2020-01-02'),color='k', linestyle='--', lw=4)
plt.text(x=np.datetime64('2020-01-02'), y=10, s=' foo-the-bar ', fontsize=28, horizontalalignment='left')
ax2 = ax.twinx()
ax2 = sns.lineplot(x='dt', y='bar', data=d2, ax=ax2, color='green')
plt.yticks(fontsize=16)
ax2.plot([], '-g', label = 'other axis in legend')
ax2.set_ylabel('ratio', fontsize=28)
plt.show()
It is more or less nice. But when adding in subplots to combine multiple measurements into a single figure sharing the x-axis (i.e. saving space and writing the dates over and over) the following fails to work and completely distorts the plot
ax0 = plt.subplot(211)
ax2 = ax0.twinx()
ax3 = plt.subplot(212)
ax4 = ax3.twinx()
ax = sns.lineplot(x='dt', y='foo', data=df, hue='category', ax=ax0)
ax.set_ylabel('asdf', fontsize=28)
ax.plot([], '-g', label = 'other axis in legend')
plt.legend(fontsize='x-large')
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles=handles[1:], labels=labels[1:], fontsize='large', loc='lower left')
plt.xticks(rotation=90, horizontalalignment='center', fontsize=28)
plt.xlabel('')
plt.yticks(fontsize=16)
plt.axvline(x=np.datetime64('2020-01-02'),color='k', linestyle='--', lw=4)
plt.text(x=np.datetime64('2020-01-02'), y=10, s=' foo-the-bar ', fontsize=28, horizontalalignment='left')
#ax2 = ax.twinx()
ax2 = sns.lineplot(x='dt', y='bar', data=df, ax=ax2, color='green')
plt.yticks(fontsize=16)
ax2.plot([], '-g', label = 'other axis in legend')
ax2.set_ylabel('ratio', fontsize=28)
plt.show()
# TODO second plot is missing
Problems always arise when trying to mix the object-oriented syntax and the pyplot interface.
pyplot functions (plt.XXX) only affect the current axes (generally the latest created, in your case ax4). When you have several axes, it is generally much better to use the OO functions so that there is no ambiguity about which axes you are working on.
Additionally, you might want to through a tight_layout() at the end of your code to automatically adjust the position of your axes to give enough room for your labels
plt.figure()
ax0 = plt.subplot(211)
ax2 = ax0.twinx()
ax3 = plt.subplot(212)
ax4 = ax3.twinx()
ax = sns.lineplot(x='dt', y='foo', data=df, hue='category', ax=ax0)
ax.set_ylabel('asdf', fontsize=28)
ax.plot([], '-g', label = 'other axis in legend')
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles=handles[1:], labels=labels[1:], fontsize='large', loc='lower left')
ax.set_xticklabels(ax.get_xticklabels(), rotation=90, horizontalalignment='center', fontsize=28)
ax.set_xlabel('')
ax.tick_params(axis='y', labelsize=16)
ax.axvline(x=np.datetime64('2020-01-02'),color='k', linestyle='--', lw=4)
ax.text(x=np.datetime64('2020-01-02'), y=10, s=' foo-the-bar ', fontsize=28, horizontalalignment='left')
#ax2 = ax.twinx()
ax2 = sns.lineplot(x='dt', y='bar', data=df, ax=ax2, color='green')
ax2.tick_params(axis='y', labelsize=16)
ax2.plot([], '-g', label = 'other axis in legend')
ax2.set_ylabel('ratio', fontsize=28)
plt.tight_layout()
plt.show()