Integration of a piecewise regression in a subplot - matplotlib

I have the following code of a piecewise_regression:
data = data_heatmap_2017.copy()
data = data[['tre200h0_2017','Leistung:']].dropna()
xx = data['tre200h0_2017'].values.tolist()
yy = data['Leistung:'].values.tolist()
pw_fit = piecewise_regression.Fit(xx, yy, n_breakpoints=1)
pw_fit.summary()
If I do a single plot with the code below, I get a diagram piecewise_regression:
# Plot the data, fit, breakpoints and confidence intervals
pw_fit.plot_data(s=0.1)
# Pass in standard matplotlib keywords to control any of the plots
pw_fit.plot_fit(color="red", linewidth=2)
pw_fit.plot_breakpoints()
pw_fit.plot_breakpoint_confidence_intervals()
plt.xlabel("Lufttemperatur [°C]")
plt.ylabel("Leistung [kW]")
plt.show()
plt.close()
Now I would like to integrate the diagram piecewise regression within this subplots on position ax10:
fig, axs = plt.subplots(2, 5, figsize=(60,50), dpi=(100))
ax10 = axs[1,0]
ax10.set_title('2017, Signatur, Zähler: ' + Zaehler)
ax10.pw_fit.plot_data(s=0.1)
ax10.pw_fit.plot_fit(color="red", linewidth=2)
ax10.set_xlabel('Lufttemperatur [°C]')
ax10.set_ylabel('Leistung [kW]')
ax10.axis([-15, 35, min_Power, max_Power])
plt.show()
plt.close()
unfortunately the lines
ax10.pw_fit.plot_data(s=0.1)
ax10.pw_fit.plot_fit(color="red", linewidth=2)
do not work with the prefix ax10. I get an AttributeError 'AxesSubplot' object has no attribute 'pw_fit'. Any idea how to solve this? Thank you!

Related

Logit scale in Plotly Express

My goal is to get a probability plot with the logit scale using Plotly Express (px).
In Matplotlib (plt) this is possible:
x, y = ([1, 2, 3], [1, 3, 2])
fig, ax = plt.subplots()
ax.scatter(x, y)
ax.set_yscale("logit")
Is there any comparable functionality in px?
The workaround I am trying currently is to get these ticks from plt and give them as parameters to px. That does work, but only changes the tick labels, not the actual scale of the y axis:
ytickvals = ax.get_yticks()
fig = px.scatter(x, y)
layout = dict(
yaxis=dict(
tickmode="array",
tickvals=ytickvals
)
)
fig.update_layout(layout)
How can I set the scale of the Plotly plot to be like the logit scale of Matplotlib?
Plotly API documentation doesn't know the term "logit" and plotly.graph_objects.layout.YAxis seems to not have a way of setting the scale.
PS, bonus question: why do my ticks not get displayed with the suffix using ticksuffix=" %" and showticksuffix="all"?

How to customize matplotlib plots using gcf() or gca()?

I am using a package called shap which has a integrated plot function. However i want to adjust some things like the labels, legend, coloring, size etc.
apparently due to the developer thats possible via using plt.gcf().
I call the plot like this, this will give a figure object but i am not sure how to use it:
fig = shap.summary_plot(shap_values_DT, data_train,color=plt.get_cmap("tab10"), show=False)
ax = plt.subplot()
UPDATE / SOLUTION
Finally i got everything adjusted as i wanted it by doing the following:
shap.summary_plot(shap_values_DT, data_train, color=plt.get_cmap("tab10"), show=False)
fig = plt.gcf()
fig.set_figheight(12)
fig.set_figwidth(14)
ax = plt.gca()
ax.set_xlabel(r'durchschnittliche SHAP Werte $\vert\sigma_{ij}\vert$', fontsize=16)
ax.set_ylabel('Inputparameter', fontsize=16)
ylabels = string_latexer([tick.get_text() for tick in ax.get_yticklabels()])
ax.set_yticklabels(ylabels)
leg = ax.legend()
for l in leg.get_texts(): l.set_text(l.get_text().replace('Class', 'Klasse'))
plt.show()
Finally i got everything adjusted as i wanted it by doing the following:
shap.summary_plot(shap_values_DT, data_train, color=plt.get_cmap("tab10"), show=False)
fig = plt.gcf()
fig.set_figheight(12)
fig.set_figwidth(14)
ax = plt.gca()
ax.set_xlabel(r'durchschnittliche SHAP Werte $\vert\sigma_{ij}\vert$', fontsize=16)
ax.set_ylabel('Inputparameter', fontsize=16)
ylabels = string_latexer([tick.get_text() for tick in ax.get_yticklabels()])
ax.set_yticklabels(ylabels)
leg = ax.legend()
for l in leg.get_texts(): l.set_text(l.get_text().replace('Class', 'Klasse'))
plt.show()
I have not used shap yet, but maybe you can modify in the following way:
shap.summary_plot(shap_values_DT, data_train,color=plt.get_cmap("tab10"), show=False)
plt.title('my custom title')
plt.savefig('test.png')
Update
From the official documentation, I read
import xgboost
import shap
# load JS visualization code to notebook
shap.initjs()
# train XGBoost model
X,y = shap.datasets.boston()
model = xgboost.train({"learning_rate": 0.01}, xgboost.DMatrix(X, label=y), 100)
# explain the model's predictions using SHAP values
# (same syntax works for LightGBM, CatBoost, and scikit-learn models)
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)
# visualize the first prediction's explanation (use matplotlib=True to avoid Javascript)
shap.force_plot(explainer.expected_value, shap_values[0,:], X.iloc[0,:])
I quickly tried the example and it seems to work, if you add the matplotlib=True option. Nevertheless, not all functions seem to support it...

How to format xticklabels in a confusion matrix plotted with scikit-learn / matplotlib?

I've plotted a confusion matrix with scikit-learn / matplotlib thanks to different code examples I found on the web, but I'm stuck at finding how to add space between the xticklabels and the main title. As you can see on the image below, the plot title and the xticklabels are overlapping (+ the ylabel 'True' is cut out).
Link to my confusion matrix image
Here is the function I use:
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
PLOTS = '/plots/' # Output folder
def plt_confusion_matrix(y_test, y_pred, normalize=False, title="Confusion matrix"):
"""
Plots a nice confusion matrix.
:param y_test: list of predicted labels
:param y_pred: list of labels that should have been predicted.
:param normalize: boolean. If False, the plots shows the number of sentences predicted.
If True, shows the percentage of sentences predicted.
:param title: string. Title of the plot.
:return: Nothing but saves the plot as a PNG file and shows it.
"""
labels = list(set(y_pred))
cm = confusion_matrix(y_test, y_pred, labels)
fig = plt.figure()
ax = fig.add_subplot(111)
cax = ax.matshow(cm, cmap=plt.cm.binary, interpolation='nearest')
if normalize:
cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
fig.suptitle(title, fontsize=14, wrap=True)
fig.colorbar(cax)
ax.set_xticklabels([''] + labels, rotation=45)
ax.set_yticklabels([''] + labels)
plt.xlabel('Predicted')
plt.ylabel('True')
plt.subplots_adjust(hspace=0.6)
fmt = '.2f' if normalize else 'd'
thresh = cm.max() / 1.5 if normalize else cm.max() / 2
for i in range(cm.shape[0]):
for j in range(cm.shape[1]):
ax.text(j, i, format(cm[i, j], fmt),
ha="center", va="center",
color="white" if cm[i, j] > thresh else "black")
plt.savefig(PLOTS + title)
plt.show()
I had to rotate the xticklabels because they are too long and otherwise overlapping each other horizontally, and I had to wrap the title because it is also too long and could not otherwise be displayed entirely in the image.
I've seen in another post that xticklabels can also be placed underneath the figure (like in this stackoverflow post), so maybe it could be a solution, however I haven't understood how to make it.
How do I solve the problem?
either to add some space between the title and the xticklabels
(making them appear entirely btw);
or to make the ylabel 'True' visible
or to move the xticklabels under the figure.
Edit : I tried both of geekzeus solutions, without success...
Result with geekzeus' 1st solution : See confusion matrix
Result with geekzeus' 2nd solution : See confusion matrix
Do it like this
ax.set_xlabel('Predicted labels')
ax.set_ylabel('True labels')
ax.set_title('Confusion Matrix')
#xaxisticks
ax.xaxis.set_ticklabels(['A', 'B'])
#yaxis ticks
ax.yaxis.set_ticklabels(['B', 'A'])
OR
use seaborn with matplotlib,you can also directly provide list variable to ticks
import seaborn as sns
import matplotlib.pyplot as plt
cm = confusion_matrix(true_classes, predicted_classes)
ax= plt.subplot()
sns.heatmap(cm, annot=True, ax = ax); #annot=True to annotate cells
# labels, title and ticks
ax.set_xlabel('Predicted labels')
ax.set_ylabel('True labels')
ax.set_title('Confusion Matrix')
ax.xaxis.set_ticklabels(['A', 'B'])
ax.yaxis.set_ticklabels(['B', 'A'])
You can specify the location of the title using parameters x and y. If you tweak the values of y, the desired plot can be generated.
fig.suptitle(title, fontsize=14, wrap=True, y=1.2)

Matplotlib: Assign legend to different figures

Inside a loop I am calculating some things and then I want to plot them in two different figures. I have set up the figures as
susc_comp, (ax1,ax2) = plt.subplots( 2, 1, sharex=True, sharey='none', figsize=(8.3,11.7))
cole_cole, (ax3) = plt.subplots( 1, 1, sharex='none', sharey='none', figsize=(8.3,11.7))
for j,temp in enumerate(indexes_T[i]):
Calculate and plot in the corresponding ax1,ax2,ax3
plt.legend(loc=0, fontsize='small', numpoints = 1, ncol=(len(indexes_T[i]))/2, frameon=False)
susc_comp.savefig('suscp_components'+str(field)+'Oe.png', dpi=300)
cole_cole.savefig('Cole_Cole'+str(field)+'Oe.png', dpi=300)
But I get the legend only in the sus_comp figure (it is the same legend for both figures). How can I select the figure and add the legend to each of them?
Thank you very much!
You can call figure.legend directly (although I think this may have less functionality than plt.legend). Therefore, I would do this a different way.
The question states that both legends are the same. In addition, the second figure only has 1 axes in it. Therefore one solution would be to get the handles and labels from ax3, then manually apply those to both figures. A simplified example is below:
import matplotlib.pyplot as plt
susc_comp, (ax1, ax2) = plt.subplots(1,2)
cole_cole, ax3 = plt.subplots()
ax1.plot([1,2,3], label="Test1")
ax2.plot([3,2,1], label="Test2")
ax3.plot([1,2,3], label="Test1")
ax3.plot([3,2,1], label="Test2")
handles, labels = ax3.get_legend_handles_labels()
ax2.legend(handles, labels, loc=1, fontsize='small', numpoints = 1)
ax3.legend(handles, labels, loc=1, fontsize='small', numpoints = 1)
plt.show()
This gives the following 2 figures:

Multi axes timeseries line graph using matplotlib

I am trying to create multi axis line chart where the x-axis are dates using matplotlib. As you can see in the picture below, the lines are close but all seem to be finishing on the left axis which is not correct.
Here is my code:
df.Date = pd.to_datetime(df.Date)
fig, ax = plt.subplots()
ax2= ax.twinx()
ax2.set_frame_on(True)
ax2.patch.set_visible(False)
fig.subplots_adjust(right=0.75)
years = YearLocator() # every year
months = MonthLocator() # every month
yearsFmt = DateFormatter('%Y')
ax.plot_date(df.Date,df.A, fmt="r-")
ax.plot_date(df.Date,df.B, fmt="b-")
ax2.plot_date(df.Date,df.C, fmt="y-")
ax2.plot_date(df.Date,df.D, fmt="g-")
ax.xaxis.set_major_locator(years)
ax.xaxis.set_major_formatter(yearsFmt)
ax.xaxis.set_minor_locator(months)
ax.autoscale_view()
ax2.xaxis.set_major_locator(years)
ax2.xaxis.set_major_formatter(yearsFmt)
ax2.xaxis.set_minor_locator(months)
ax2.autoscale_view()
plt.setp(ax.get_xticklabels(), fontsize=10, rotation='vertical')
plt.setp(ax2.get_xticklabels(), fontsize=10, rotation='vertical')
ax.fmt_xdata = DateFormatter('%b\n%Y')
ax2.fmt_xdata = DateFormatter('%b\n%Y')
fig.autofmt_xdate()
plt.setp(ax.get_xticklabels(), fontsize=10, rotation='vertical')
ax.set_ylabel('(%)')
ax2.set_ylabel('(%)')
ax2.set_xlabel('Date')
plt.title('Chart 1. ', fontsize=8, weight= 'bold')
plt.tight_layout()
plt.show()
need to use df1= df.sort_values(by='Date'). When i took a closer look at the data, there were a few dates out of order towards the end of the dataset that were causing the plot to revert back to 2002, causing the line to move towards the left of the graph.