Change the features of Prophet plot - python-3.x

While using model.plot(forecast) the figure that appears has small labels and x/y values.
Is there any way to customize customize prophet's figures ?

I found there is a way to customize the options in fbprophet such as increasing size of labels or tick values.
fig = model.plot(forecast, xlabel='Date', ylabel='Value')
ax = fig.gca()
ax.set_title("Title", size=34)
ax.set_xlabel("X", size=34)
ax.set_ylabel("Y", size=34)
ax.tick_params(axis="x", labelsize=24)
ax.tick_params(axis="y", labelsize=24)

The Prophet.plot is quite limiting.
However, the fbprophet.plot.plot function allows the option of specifying the figure size. The default is (10, 6) e.g.
from fbprophet.plot import plot
plot(model, forecast, figsize=(20, 12))

Related

How to plot hyperparameter tuning results?

I have the result of a grid search as follows.
"trial","learning_rate","batch_size","accuracy","f1","loss"
1,0.000007,70,0.789,0.862,0.467
2,0.000008,100,0.710,0.822,0.563
3,0.000008,90,0.823,0.874,0.524
4,0.000007,90,0.833,0.878,0.492
5,0.000009,110,0.715,0.825,0.509
6,0.000006,90,0.883,0.885,0.932
7,0.000009,80,0.850,0.895,0.408
8,0.000006,110,0.683,0.812,0.593
9,0.000005,90,0.769,0.848,0.468
10,0.000005,80,0.816,0.868,0.462
11,0.000003,100,0.852,0.901,0.448
12,0.000004,100,0.705,0.818,0.512
13,0.000003,110,0.708,0.818,0.567
14,0.000002,90,0.683,0.812,0.552
15,0.000008,100,0.791,0.857,0.438
16,0.000006,110,0.683,0.812,0.604
17,0.000007,70,0.693,0.816,0.592
18,0.000005,110,0.830,0.883,0.892
19,0.000004,90,0.693,0.816,0.591
20,0.000008,70,0.696,0.818,0.570
I want to create a plot more or less similar to this using matplotlib. I know this is plotted using weights and biases but I cannot use that.
Though I don't care for the inference part. I just want the plot. I've been trying to do this using twinx but have not been successful. This is what I have so far.
from csv import DictReader
import matplotlib.pyplot as plt
trials = list(DictReader(open("hparams_trials.csv")))
trials = {f"trial_{trial['trial']}": [int(trial["batch_size"]),
float(trial["f1"]),
float(trial["loss"]),
float(trial["accuracy"]),
float(trial["learning_rate"])] for trial in trials}
items = ["batch_size", "f1", "loss", "accuracy", "learning_rate"]
host_y_values_index = 0
parts_y_values_indexes = [1, 2, 3, 4]
fig, host = plt.subplots(figsize=(8, 5)) # (width, height) in inches
fig.dpi = 300. # Figure resolution
# Removing extra spines
host.spines.top.set_visible(False)
host.spines.bottom.set_visible(False)
host.spines.right.set_visible(False)
# Creating subplots which share the same x axis.
parts = {index: host.twinx() for index in parts_y_values_indexes}
# Setting the limits of the host plot
host.set_xlim(0, len(trials["trial_1"]))
host.set_ylim(min([i[host_y_values_index] for i in trials.values()]),
max([i[host_y_values_index] for i in trials.values()]))
# Removing the extra spines from the other plots and setting y limits
for part in parts_y_values_indexes:
parts[part].spines.top.set_visible(False)
parts[part].spines.bottom.set_visible(False)
parts[part].set_ylim(min([trial[part] for trial in trials.values()]),
max([trial[part] for trial in trials.values()]))
# Colors of the trials
colors = ["gold", "lightcoral", "maroon", "springgreen", "cyan", "steelblue", "darkmagenta", "fuchsia", "crimson",
"lime", "mediumblue", "cadetblue", "dodgerblue", "olivedrab", "sandybrown", "bisque", "orangered", "black",
"rosybrown", "chocolate"]
# The plots
plots = []
# Plotting the trials. This is where I'm having problems with.
for index, trial in enumerate(trials):
plots.append(host.plot(items, trials[trial], color=colors[index], label=trial)[0])
# Creating the legend
host.legend(handles=plots, fancybox=True, loc='right', facecolor="snow", bbox_to_anchor=(1.02, 0.495), framealpha=1)
# Defining the positions of the spines.
spines_positions = [-104.85 * i for i in parts_y_values_indexes]
# Repositioning the spines
for part in parts_y_values_indexes:
parts[part].spines['right'].set_position(('outward', spines_positions[-part]))
# Adjust spacings around fig
fig.tight_layout()
host.grid(True)
# This is better than the one above but it appears on top of the legend.
# plt.grid(True)
plt.draw()
plt.show()
I'm having several problems with that code. First, I cannot place each value of a single trial based on a different spine and then connect them to one another. What I mean is that each trial has a batch size, an f1, a loss, accuracy and a learning rate. Each of those need to be plotted based on their own spine while connected to each other in that order. However, I cannot plot them based their dedicated spines and then connect them to one another to have a line plot per trial. Accordingly, for now I have placed everything in the host plot but I know that is wrong and have no idea what the correct approach is. Second problem, the ticks of the learning rate change. It gets shown as a range of 2 to 9 and then a 1e-6 appears at the top. I want to keep the original value. Third problem is probably part of the second one. The 1e-6 appears at the top right above the legend rather than above the spine for some reason. I'm struggling with resolving all three of these problems and would appreciate any help anyone can provide. If what I am doing is totally wrong, please help me in finding the correct solution. I'm somewhat going in circles here and haven't been able to find any working solutions so far.

Is it possible to extract the default tick locations from the primary axis and pass it to a secondary access with matplotlib?

When making a plot with with
fig, ax = plt.subplots()
x=[1,2,3,4,5,6,7,8,9,10]
y=[1,2,3,4,5,6,7,8,9,10]
ax.plot(x,y)
plt.show()
matplotlib will determine the tick spacing/location and value of the tick. Is there are way to extract this automatic spacing/location AND the value? I want to do this so i can pass it to
set_xticks()
for my secondary axis (using twiny()) then use set_ticklabels() with a custom label. I realise I could use secondary axes giving both a forward and inverse function however providing an inverse function is not feasible for the goal of my code.
So in the image below, the ticks are only showing at 2,4,6,8,10 rather than all the values of x and I want to somehow extract these values and position so I can pass to set_xticks() and then change the tick labels (on a second x axis created with twiny).
UPDATE
When using the fix suggested it works well for the x axis. However, it does not work well for the y-axis. For the y-axis it seems to take the dataset values for the y ticks only. My code is:
ax4 = ax.twinx()
ax4.yaxis.set_ticks_position('left')
ax4.yaxis.set_label_position('left')
ax4.spines["left"].set_position(("axes", -0.10))
ax4.set_ylabel(self.y_2ndary_label, fontweight = 'bold')
Y = ax.get_yticks()
ax4.yaxis.set_ticks(Y)
ax4.yaxis.set_ticklabels( Y*Y )
ax4.set_ylim(ax.get_ylim())
fig.set_size_inches(8, 8)
plt.show()
but this gives me the following plot. The plot after is the original Y axis. This is not the case when I do this on the x-axis. Any ideas?
# From "get_xticks" Doc: The locations are not clipped to the current axis limits
# and hence may contain locations that are not visible in the output.
current_x_ticks = ax.get_xticks()
current_x_limits = ax.get_xlim()
ax.set_yticks(current_x_ticks) # Use this before "set_ylim"
ax.set_ylim(current_x_limits)
plt.show()

Bar format (kind) is not displaying the right plot (matplotlib)

I need to do a plot using three variables. One of them should be on the secondary Y axis in bar format (kind), the remaining variables (two) should be on the left axis using a simple line. However, I got the following chart:
When I use the three variables in line format I get the right plot (which is not very useful for a visual analysis):
I did a quick test using a small sample from my data (code below). I get the right pic when I use bar format for the third one.
I wonder, what is going on? Is there a problem with the data size (which I dont think so bcs I get less than 100 rows)?
df2 = pd.DataFrame({'ind':[120.29, 125.45, 127.37, 130.39, 128.30],
'var1':[129.907990, 129.571185, 129.234380, 128.897574, 128.560769],
'var2':[-0.074037, -0.031806, -0.014426, 0.011578, -0.002028]})
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
df2['ind'].plot(ax=ax1)
df2['var1'].plot(ax=ax1)
df2['var2'].plot(kind='bar', ax=ax2, color='r')
plt.show()
PD: In addition, I noted that in the third pic the line is behind the bar. How can I change that?
I found the solution for this (this link helped me a lot ). Basically, it is based on the index you set up previously.
This is the new code:
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(df2.index, df2['ind'])
ax1.plot(df2.index, df2['var1'])
ax2.bar(df2.index, df2['var2'], color='r')
plt.show()
Hope this helps.

Rotate figure - Flopy

I am using functions, e.x: ml.dis.top.plot(). I would like to rotate these figures and delete titles. How can I do that?
plt.title('') seems to work for titles but I cannot rotate these figures. Here is the part of the script:
fig = plt.figure(figsize=(75, 75))
plt.subplot(1,1,1,aspect='equal')
mf.dis.top.plot(contour=True, colorbar=True)
plt.title('')
plt.savefig('top_plot.png')
So there are different ways that you can make model plots in flopy. You are using the quick and easy way to plot one of our arrays. What you probably want to do is use the ModelMap capability, which is described in https://github.com/modflowpy/flopy/blob/develop/examples/Notebooks/flopy3_MapExample.ipynb. This will give you full control over your figure, including rotation and offset and will allow you to customize the title and anything else you'll need to do. The code might look something like the following:
fig = plt.figure(figsize=(75, 75))
ax = plt.subplot(1, 1, 1, aspect='equal')
modelmap = flopy.plot.ModelMap(model=mf, rotation=14)
modelmap.contour_array(mf.dis.top.array)
plt.savefig('top_plot.png')

healpy: Formatting subplots

I want to plot many subplots in one figure using healpy. How to:
Set the position of the colorbar?
Set the tick and ticklabel of colorbar?
Set the position and size of the subplots?
I want to generate a plot such as figure 1, which is plotted in MATLAB, based on general coordinates
Right now, I only plot it as follows using healpy:
A similar code to produce figure 3 (similar to figure2) is as follow:
import numpy as np
import healpy as hp
degree = 4
nside = 2**degree
num_Pixel = hp.nside2npix(nside)
m = np.arange(num_Pixel)
margins = [[0.02,0,0,0],[0.01,0,0,0],[0.01,0,0.01,0],
[0.02,0,0,0],[0.01,0,0,0],[0.01,0,0.01,0],
[0.02,0.05,0,0],[0.01,0.05,0,0],[0.01,0.05,0.01,0]]
title = [
'Equinox', 'Jun. Solstice', 'Dec. Solstice',
'','','','','','']
for ifig in range(1,10):
if ifig < 7:
hp.cartview(
m, sub=330+ifig, margins=margins[ifig1],
cbar=False, title=title[ifig-1])
else:
hp.cartview(
m, sub=330+ifig, margins=margins[ifig-1],
cbar=True, title=title[ifig-1])
The code produced the figure 3
I'm afraid healpy doesn't come with a good way to handle the colorbar, ticks, ticklabels, the axes etc.
The best way forward would be to generate FITS images, based on your HEALPix map (e.g. using hp.cartview(..., return_projected_map=True) or using the reproject package).
You also need to generate the right FITS header for that, astropy would be the right tool for that (how-to manipulate FITS headers).
Once you have that, you can use the excellent WCSAxes framework within astropy, which gives you plenty of well-documented customization options.

Resources