11import copy
22import functools
33import itertools
4- from typing import Literal
4+ from typing import Literal , Optional
55
66import colorsys
77import matplotlib as mpl
@@ -135,17 +135,25 @@ def palette(
135135def visualization (
136136 * ,
137137 bins : pd .DataFrame ,
138+ bins2 : Optional [pd .DataFrame ] = None ,
138139 palette : list [list [float ]],
139140 n_bins : str | int = "auto" ,
140141 kind : Literal ["histogram" , "boxplot" ] = "histogram" ,
141142 ax = None ,
143+ output_name : str = "Output 1" ,
144+ output_name2 : str = "Output 2" ,
145+ xlim : Optional [tuple [float , float ]] = None ,
146+ ylim : Optional [tuple [float , float ]] = None ,
147+ r_scatter : float = 1.0 ,
142148) -> plt .Axes :
143149 """Histogram plot of scenarios.
144150
145151 Parameters
146152 ----------
147153 bins : DataFrame
148154 Multidimensional bins.
155+ bins2 : DataFrame
156+ Multidimensional bins for output 2
149157 palette : list of int of size (n, 4)
150158 List of colours corresponding to scenarios.
151159 n_bins : str or int
@@ -154,16 +162,85 @@ def visualization(
154162 Histogram or Box Plot.
155163 ax : Axes, optional
156164 Matplotlib axis.
165+ output_name : str, default "Output 1"
166+ Name of the primary output variable.
167+ output_name2 : str, default "Output 2"
168+ Name of the second output variable.
169+ xlim : tuple of float, optional
170+ Minimum and maximum values for the x-axis (Output 1).
171+ ylim : tuple of float, optional
172+ Minimum and maximum values for the y-axis (Output 2).
173+ r_scatter : float, default 1.0
174+ The portion of data points displayed on the scatter plot (0 to 1).
157175
158176 Returns
159177 -------
178+ axs : Axes
179+ Matplotlib axis for two-output graph.
160180 ax : Axes
161181 Matplotlib axis.
162182
163183 """
164184 # needed to get the correct stacking order
165185 bins .columns = pd .RangeIndex (start = len (bins .columns ), stop = 0 , step = - 1 )
166186
187+ if bins2 is not None :
188+ fig , axs = plt .subplots (2 , 2 , sharex = "col" , sharey = "row" , figsize = (8 , 8 ))
189+ axs [0 , 1 ].axis ("off" )
190+
191+ sns .histplot (
192+ bins ,
193+ multiple = "stack" ,
194+ stat = "probability" ,
195+ palette = palette ,
196+ common_bins = True ,
197+ common_norm = True ,
198+ bins = n_bins ,
199+ legend = False ,
200+ ax = axs [0 , 0 ],
201+ )
202+ axs [0 , 0 ].set_xlim (xlim )
203+ axs [0 , 0 ].set_box_aspect (1 )
204+ axs [0 , 0 ].axis ("off" )
205+
206+ data = pd .concat ([pd .melt (bins ), pd .melt (bins2 )["value" ]], axis = 1 )
207+ data .columns = ["c" , "x" , "y" ]
208+
209+ if r_scatter < 1.0 :
210+ data = data .sample (frac = r_scatter )
211+
212+ sns .scatterplot (
213+ data = data ,
214+ x = "x" ,
215+ y = "y" ,
216+ hue = "c" ,
217+ palette = palette ,
218+ ax = axs [1 , 0 ],
219+ legend = False ,
220+ )
221+ axs [1 , 0 ].set (xlabel = output_name , ylabel = output_name2 )
222+ axs [1 , 0 ].set_box_aspect (1 )
223+
224+ sns .histplot (
225+ data ,
226+ y = "y" ,
227+ hue = "c" ,
228+ multiple = "stack" ,
229+ stat = "probability" ,
230+ palette = palette ,
231+ common_bins = True ,
232+ common_norm = True ,
233+ bins = 40 ,
234+ legend = False ,
235+ ax = axs [1 , 1 ],
236+ )
237+ axs [1 , 1 ].set_ylim (ylim )
238+ axs [1 , 1 ].set_box_aspect (1 )
239+ axs [1 , 1 ].axis ("off" )
240+
241+ fig .subplots_adjust (wspace = - 0.015 , hspace = 0 )
242+ return axs [1 , 0 ]
243+
167244 if kind == "histogram" :
168245 ax = sns .histplot (
169246 bins ,
0 commit comments