├── .gitignore ├── LICENSE ├── README.md ├── Tutorial1-Fig-Ax.py ├── Tutorial2_lineplot_color_legend.py ├── examples ├── cmap.ipynb ├── extend_ax.ipynb ├── gridspec.ipynb ├── legend.ipynb ├── markersize.ipynb ├── stacked_legends.ipynb └── yaxis_tick_on_right.ipynb ├── plotly ├── index.html ├── network.html └── plotly.py ├── rcParams.txt ├── sankey ├── Sankey_tutorial.py ├── sankey_tutorial.pptx └── sankey_tutorial_bezier.ai ├── tutorial3_boxplot_etc.py ├── tutorial5_seaborn.py └── tutorial_4_violin_dendrogram.py /.gitignore: -------------------------------------------------------------------------------- 1 | <<<<<<< HEAD 2 | 3 | ======= 4 | **/.DS_Store 5 | .ipynb_checkpoints/** 6 | >>>>>>> 7164dfc56abe05217dab383c27613f404711b903 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Guangyuan(Frank) Li 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python_visualization_tutorial 2 | A comprehensive guide of how to make publication-ready figures in python 3 | 4 | I am planning to share how to make publication-quality figures in python, I will publish all the tutorial in TowardDatascience Medium platform. In the meantime, I will share some sporadic tricks as separate jupyter nodebook at the bottom of the page. 5 | 6 | ## Phase I: Static Figure (basic matplotlib and seaborn) 7 | 1. [Tutorial I (Understanding Fig and Ax object)](https://towardsdatascience.com/making-publication-quality-figures-in-python-part-i-fig-and-axes-d86c3903ad9b) 8 | 2. [Turorial II (Line plot, colors and legends)](https://frankligy.medium.com/making-publication-quality-figures-in-python-part-ii-line-plot-legends-colors-4430a5891706) 9 | 3. [Tutorial III (boxplot, scatter plot, heatmap, colormap, barplot, histogram)](https://frankligy.medium.com/making-publication-quality-figures-in-python-part-iii-box-plot-bar-plot-scatter-plot-407fa457449) 10 | 4. [Tutorial IV (Violin plot, dendrogram)](https://towardsdatascience.com/making-publication-quality-figures-in-python-part-iv-violin-plot-and-dendrogram-ed0bb8b23ddd) 11 | 5. [Tutorial V (Seaborn)](https://frankligy.medium.com/all-you-need-to-know-about-seaborn-6678a02f31ff) 12 | 13 | ## Phase II: Advanced tutorials 14 | 1. [Plotly, interactive network](https://frankligy.medium.com/plotly-meets-scientific-visualization-8c2074f032cb) 15 | 2. [Sankey plot strategies (Matplotlib Path and Patch)](https://frankligy.medium.com/the-essence-of-drawing-sankey-plot-491fb2cb234) 16 | 17 | 18 | ## Do you want to know some tricks? 19 | 1. [gridspec](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/gridspec.ipynb) 20 | 2. [how to move yaxis ticks to the right spines](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/yaxis_tick_on_right.ipynb) 21 | 3. [how to extract certain number of colors?](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/cmap.ipynb) 22 | 4. [legend,flexibly adjust it](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/legend.ipynb) 23 | 5. [transformation, bbox](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/extend_ax.ipynb) 24 | 6. [stacked legend](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/stacked_legends.ipynb) 25 | 7. [Markersize](https://github.com/frankligy/python_visualization_tutorial/blob/main/examples/markersize.ipynb) 26 | 8. stay tuned 27 | -------------------------------------------------------------------------------- /Tutorial1-Fig-Ax.py: -------------------------------------------------------------------------------- 1 | import matplotlib as mpl 2 | import matplotlib.pyplot as plt 3 | from matplotlib.ticker import MultipleLocator,FormatStrFormatter,MaxNLocator 4 | 5 | a = pd.Series(list(mpl.rcParams.keys())) 6 | 7 | 8 | mpl.rcParams['pdf.fonttype'] = 42 9 | mpl.rcParams['ps.fonttype'] = 42 10 | mpl.rcParams['font.family'] = 'Arial' 11 | 12 | fig = plt.figure() 13 | mpl.rcParams['figure.figsize'] # [6.4,4.8] 6.4 is the width, 4.8 is the height 14 | fig = plt.figure(figsize=(10,6)) 15 | ax = plt.axes((0.1,0.1,0.5,0.8)) 16 | ax.spines['right'].set_visible(False) 17 | ax.spines['left'].set_visible(False) 18 | ax.spines['bottom'].set_visible(False) 19 | ax.spines['top'].set_visible(False) 20 | ax.tick_params(axis='x',which='major',direction='out',length=10,width=5,color='red',pad=15,labelsize=15,labelcolor='green', 21 | labelrotation=15) 22 | ax.set_xticks([0.2,1]) 23 | ax.set_xticklabels(['pos1','pos2']) 24 | 25 | ax.yaxis.set_major_locator(MultipleLocator(0.5)) 26 | ax.yaxis.set_minor_locator(MultipleLocator(0.1)) 27 | 28 | a=ax.yaxis.get_major_locator() 29 | b=ax.yaxis.get_major_formatter() 30 | 31 | ax.grid(True,which='major',axis='both',alpha=0.3) 32 | 33 | c = ax.get_xticks() 34 | d = ax.get_xticklabels() 35 | 36 | fig,axes = plt.subplots(nrows=4,ncols=4,figsize=(10,6)) 37 | fig,axes = plt.subplots(nrows=4,ncols=4,figsize=(10,6),gridspec_kw={'wspace':0.5,'hspace':0.5}) 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Tutorial2_lineplot_color_legend.py: -------------------------------------------------------------------------------- 1 | import matplotlib as mpl 2 | import matplotlib.pyplot as plt 3 | from matplotlib.ticker import MultipleLocator,FormatStrFormatter,MaxNLocator 4 | import numpy as np 5 | import pandas as pd 6 | 7 | mpl.rcParams['pdf.fonttype'] = 42 8 | mpl.rcParams['ps.fonttype'] = 42 9 | mpl.rcParams['font.family'] = 'Arial' 10 | 11 | np.random.seed(42) 12 | 13 | 14 | x = np.arange(1,11,1) 15 | y1 = np.linspace(300,400,10) 16 | y2 = np.random.randint(low=300,high=400,size=10) 17 | 18 | mpl.rcParams['lines.marker'] #None 19 | mpl.rcParams['lines.markersize'] #6.0 20 | mpl.rcParams['lines.linewidth'] # 1.5 21 | mpl.rcParams['axes.prop_cycle'] 22 | 23 | mpl.colors.to_rgb('#1f77b4') 24 | 25 | fig = plt.figure(figsize=(10,6)) 26 | ax = fig.add_axes([0.1,0.1,0.5,0.8]) 27 | p1 = ax.plot(x,y1,marker='o',markersize=8,markerfacecolor='red',markeredgecolor='black',markeredgewidth=2, 28 | linestyle='--',linewidth=3,zorder=3) 29 | p2 = ax.plot(x,y2,marker='o') 30 | ax.legend(handles=[p1[0],p2[0]],labels=['blue line','orange line'],loc='upper left',bbox_to_anchor=(1,1), 31 | title='legend',frameon=False) 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /examples/cmap.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 4, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "import matplotlib\n", 11 | "from matplotlib import cm\n", 12 | "import matplotlib.pyplot as plt\n", 13 | "import numpy as np\n", 14 | "from matplotlib import colors" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 10, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "# get discrete value from built in colormap\n", 24 | "# Method1: < 10 colors, go to this approach\n", 25 | "a = matplotlib.rcParams['axes.prop_cycle']" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 17, 31 | "metadata": {}, 32 | "outputs": [ 33 | { 34 | "data": { 35 | "text/html": [ 36 | "
'color'
'#1f77b4'
'#ff7f0e'
'#2ca02c'
'#d62728'
'#9467bd'
'#8c564b'
'#e377c2'
'#7f7f7f'
'#bcbd22'
'#17becf'
" 37 | ], 38 | "text/plain": [ 39 | "cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'])" 40 | ] 41 | }, 42 | "execution_count": 17, 43 | "metadata": {}, 44 | "output_type": "execute_result" 45 | } 46 | ], 47 | "source": [ 48 | "a" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 16, 54 | "metadata": {}, 55 | "outputs": [ 56 | { 57 | "data": { 58 | "text/plain": [ 59 | "'#1f77b4'" 60 | ] 61 | }, 62 | "execution_count": 16, 63 | "metadata": {}, 64 | "output_type": "execute_result" 65 | } 66 | ], 67 | "source": [ 68 | "list(list(a)[0].values())[0]" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 20, 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "# Method2: < 12 colors\n", 78 | "a1 = cm.get_cmap('Set3').colors[:12]" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 21, 84 | "metadata": {}, 85 | "outputs": [ 86 | { 87 | "data": { 88 | "text/plain": [ 89 | "((0.5529411764705883, 0.8274509803921568, 0.7803921568627451),\n", 90 | " (1.0, 1.0, 0.7019607843137254),\n", 91 | " (0.7450980392156863, 0.7294117647058823, 0.8549019607843137),\n", 92 | " (0.984313725490196, 0.5019607843137255, 0.4470588235294118),\n", 93 | " (0.5019607843137255, 0.6941176470588235, 0.8274509803921568),\n", 94 | " (0.9921568627450981, 0.7058823529411765, 0.3843137254901961),\n", 95 | " (0.7019607843137254, 0.8705882352941177, 0.4117647058823529),\n", 96 | " (0.9882352941176471, 0.803921568627451, 0.8980392156862745),\n", 97 | " (0.8509803921568627, 0.8509803921568627, 0.8509803921568627),\n", 98 | " (0.7372549019607844, 0.5019607843137255, 0.7411764705882353),\n", 99 | " (0.8, 0.9215686274509803, 0.7725490196078432),\n", 100 | " (1.0, 0.9294117647058824, 0.43529411764705883))" 101 | ] 102 | }, 103 | "execution_count": 21, 104 | "metadata": {}, 105 | "output_type": "execute_result" 106 | } 107 | ], 108 | "source": [ 109 | "a1" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 23, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "# Method3: < 20 colors\n", 119 | "a2 = cm.get_cmap('tab20').colors[:20]" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 24, 125 | "metadata": {}, 126 | "outputs": [ 127 | { 128 | "data": { 129 | "text/plain": [ 130 | "((0.12156862745098039, 0.4666666666666667, 0.7058823529411765),\n", 131 | " (0.6823529411764706, 0.7803921568627451, 0.9098039215686274),\n", 132 | " (1.0, 0.4980392156862745, 0.054901960784313725),\n", 133 | " (1.0, 0.7333333333333333, 0.47058823529411764),\n", 134 | " (0.17254901960784313, 0.6274509803921569, 0.17254901960784313),\n", 135 | " (0.596078431372549, 0.8745098039215686, 0.5411764705882353),\n", 136 | " (0.8392156862745098, 0.15294117647058825, 0.1568627450980392),\n", 137 | " (1.0, 0.596078431372549, 0.5882352941176471),\n", 138 | " (0.5803921568627451, 0.403921568627451, 0.7411764705882353),\n", 139 | " (0.7725490196078432, 0.6901960784313725, 0.8352941176470589),\n", 140 | " (0.5490196078431373, 0.33725490196078434, 0.29411764705882354),\n", 141 | " (0.7686274509803922, 0.611764705882353, 0.5803921568627451),\n", 142 | " (0.8901960784313725, 0.4666666666666667, 0.7607843137254902),\n", 143 | " (0.9686274509803922, 0.7137254901960784, 0.8235294117647058),\n", 144 | " (0.4980392156862745, 0.4980392156862745, 0.4980392156862745),\n", 145 | " (0.7803921568627451, 0.7803921568627451, 0.7803921568627451),\n", 146 | " (0.7372549019607844, 0.7411764705882353, 0.13333333333333333),\n", 147 | " (0.8588235294117647, 0.8588235294117647, 0.5529411764705883),\n", 148 | " (0.09019607843137255, 0.7450980392156863, 0.8117647058823529),\n", 149 | " (0.6196078431372549, 0.8549019607843137, 0.8980392156862745))" 150 | ] 151 | }, 152 | "execution_count": 24, 153 | "metadata": {}, 154 | "output_type": "execute_result" 155 | } 156 | ], 157 | "source": [ 158 | "a2" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 2, 164 | "metadata": {}, 165 | "outputs": [], 166 | "source": [ 167 | "# Method4: > 20 colors, pick colors from continuous colormap\n", 168 | "cmap = [cm.jet(round(i)) for i in np.linspace(0,255,27)]" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": 3, 174 | "metadata": {}, 175 | "outputs": [ 176 | { 177 | "data": { 178 | "text/plain": [ 179 | "[(0.0, 0.0, 0.5, 1.0),\n", 180 | " (0.0, 0.0, 0.67825311942959, 1.0),\n", 181 | " (0.0, 0.0, 0.85650623885918, 1.0),\n", 182 | " (0.0, 0.0, 1.0, 1.0),\n", 183 | " (0.0, 0.11176470588235295, 1.0, 1.0),\n", 184 | " (0.0, 0.26862745098039204, 1.0, 1.0),\n", 185 | " (0.0, 0.42549019607843136, 1.0, 1.0),\n", 186 | " (0.0, 0.5823529411764706, 1.0, 1.0),\n", 187 | " (0.0, 0.7235294117647059, 1.0, 1.0),\n", 188 | " (0.0, 0.8803921568627451, 0.9835547122074637, 1.0),\n", 189 | " (0.11068943706514844, 1.0, 0.8570524984187226, 1.0),\n", 190 | " (0.2371916508538899, 1.0, 0.7305502846299811, 1.0),\n", 191 | " (0.3636938646426312, 1.0, 0.6040480708412397, 1.0),\n", 192 | " (0.4901960784313725, 1.0, 0.4775458570524984, 1.0),\n", 193 | " (0.6040480708412397, 1.0, 0.3636938646426312, 1.0),\n", 194 | " (0.730550284629981, 1.0, 0.23719165085388993, 1.0),\n", 195 | " (0.8570524984187222, 1.0, 0.11068943706514867, 1.0),\n", 196 | " (0.9835547122074635, 0.9448075526506902, 0.0, 1.0),\n", 197 | " (1.0, 0.7995642701525056, 0.0, 1.0),\n", 198 | " (1.0, 0.6688453159041396, 0.0, 1.0),\n", 199 | " (1.0, 0.5236020334059556, 0.0, 1.0),\n", 200 | " (1.0, 0.3783587509077707, 0.0, 1.0),\n", 201 | " (1.0, 0.2331154684095862, 0.0, 1.0),\n", 202 | " (1.0, 0.08787218591140178, 0.0, 1.0),\n", 203 | " (0.8565062388591802, 0.0, 0.0, 1.0),\n", 204 | " (0.6782531194295901, 0.0, 0.0, 1.0),\n", 205 | " (0.5, 0.0, 0.0, 1.0)]" 206 | ] 207 | }, 208 | "execution_count": 3, 209 | "metadata": {}, 210 | "output_type": "execute_result" 211 | } 212 | ], 213 | "source": [ 214 | "cmap" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": 6, 220 | "metadata": {}, 221 | "outputs": [ 222 | { 223 | "name": "stdout", 224 | "output_type": "stream", 225 | "text": [ 226 | "#000080\n", 227 | "#0000ad\n", 228 | "#0000da\n", 229 | "#0000ff\n", 230 | "#001cff\n", 231 | "#0044ff\n", 232 | "#006cff\n", 233 | "#0094ff\n", 234 | "#00b8ff\n", 235 | "#00e0fb\n", 236 | "#1cffdb\n", 237 | "#3cffba\n", 238 | "#5dff9a\n", 239 | "#7dff7a\n", 240 | "#9aff5d\n", 241 | "#baff3c\n", 242 | "#dbff1c\n", 243 | "#fbf100\n", 244 | "#ffcc00\n", 245 | "#ffab00\n", 246 | "#ff8600\n", 247 | "#ff6000\n", 248 | "#ff3b00\n", 249 | "#ff1600\n", 250 | "#da0000\n", 251 | "#ad0000\n", 252 | "#800000\n" 253 | ] 254 | } 255 | ], 256 | "source": [ 257 | "# convert to hexadecimal\n", 258 | "for c in cmap:\n", 259 | " print(colors.to_hex(c))\n", 260 | "# if you want to convert back, colors.to_rgb() or to_rgba()" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "## construct custom colormap, first extract gradient using adobe online color, understand the dynamic changes of R G B channels, then specify cdict" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 26, 273 | "metadata": {}, 274 | "outputs": [], 275 | "source": [ 276 | "# Nathan's Yellow-blue schema\n", 277 | "# yellow-blue colormap\n", 278 | "cdict = {\n", 279 | " 'red':((0.0,0.0,0.0),\n", 280 | " (0.5,0.0,0.0),\n", 281 | " (1.0,1.0,1.0)),\n", 282 | " 'green':((0.0,0.8,0.8),\n", 283 | " (0.5,0.0,0.0),\n", 284 | " (1.0,1.0,1.0)),\n", 285 | " 'blue':((0.0,1.0,1.0),\n", 286 | " (0.5,0.0,0.0),\n", 287 | " (1.0,0.0,0.0))\n", 288 | "}\n", 289 | "from matplotlib.colors import LinearSegmentedColormap\n", 290 | "newcmp = LinearSegmentedColormap('yellow_blue',segmentdata=cdict)" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": 27, 296 | "metadata": {}, 297 | "outputs": [], 298 | "source": [ 299 | "# SHAP pink-blue schema\n", 300 | "cdict = {'red':((0.0,0.0,0.0),\n", 301 | " (1.0,1.0,1.0)),\n", 302 | " 'green':((0.0,0.5,0.5),\n", 303 | " (0.73,0.0,0.0),\n", 304 | " (1.0,0.0,0.0)),\n", 305 | " 'blue':((0.0,1.0,1.0),\n", 306 | " (1.0,0.0,0.0))}\n", 307 | "newcmp = LinearSegmentedColormap('testCmap', segmentdata=cdict)" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": null, 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [] 316 | } 317 | ], 318 | "metadata": { 319 | "kernelspec": { 320 | "display_name": "Python 3", 321 | "language": "python", 322 | "name": "python3" 323 | }, 324 | "language_info": { 325 | "codemirror_mode": { 326 | "name": "ipython", 327 | "version": 3 328 | }, 329 | "file_extension": ".py", 330 | "mimetype": "text/x-python", 331 | "name": "python", 332 | "nbconvert_exporter": "python", 333 | "pygments_lexer": "ipython3", 334 | "version": "3.6.12" 335 | } 336 | }, 337 | "nbformat": 4, 338 | "nbformat_minor": 4 339 | } 340 | -------------------------------------------------------------------------------- /examples/extend_ax.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "88b60d95-9ee5-44be-9063-ef831451dd6b", 6 | "metadata": {}, 7 | "source": [ 8 | "## How to extend the ax if the text protrudes out?\n", 9 | "## It is also about Transformation and Bbox" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 11, 15 | "id": "30f54a5b-4866-47f3-aefd-231ee2a82528", 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "import matplotlib.pyplot as plt\n", 20 | "import matplotlib as mpl\n", 21 | "from matplotlib.transforms import Bbox\n", 22 | "import pandas as pd\n", 23 | "import numpy as np" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 12, 29 | "id": "51c9620b-c5e2-4007-af0e-add01939e78e", 30 | "metadata": {}, 31 | "outputs": [ 32 | { 33 | "data": { 34 | "text/plain": [ 35 | "Text(0.9, 0.9, 'hhhhhhh')" 36 | ] 37 | }, 38 | "execution_count": 12, 39 | "metadata": {}, 40 | "output_type": "execute_result" 41 | }, 42 | { 43 | "data": { 44 | "image/png": "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\n", 45 | "text/plain": [ 46 | "
" 47 | ] 48 | }, 49 | "metadata": { 50 | "needs_background": "light" 51 | }, 52 | "output_type": "display_data" 53 | } 54 | ], 55 | "source": [ 56 | "# problem, as you can see, the text protrudes out the ax\n", 57 | "fig,ax = plt.subplots()\n", 58 | "ax.set_xlim([0,1])\n", 59 | "ax.set_ylim([0,1])\n", 60 | "data_text_coords = (0.9,0.9)\n", 61 | "ax.text(x=data_text_coords[0],y=data_text_coords[1],s='hhhhhhh') # default transform is ax.transData" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "id": "82d240b2-8a65-47d6-b2e7-66d5d463fb9f", 67 | "metadata": {}, 68 | "source": [ 69 | "## Easy fix:\n", 70 | "1. first save text as an object\n", 71 | "2. get text coordinate (display), inversely transform to coordinate (Ax), then adjust the x_lim" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 13, 77 | "id": "523394ae-1535-44e8-bdef-fb3eb830e952", 78 | "metadata": {}, 79 | "outputs": [ 80 | { 81 | "data": { 82 | "image/png": "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\n", 83 | "text/plain": [ 84 | "
" 85 | ] 86 | }, 87 | "metadata": { 88 | "needs_background": "light" 89 | }, 90 | "output_type": "display_data" 91 | }, 92 | { 93 | "data": { 94 | "image/png": "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\n", 95 | "text/plain": [ 96 | "
" 97 | ] 98 | }, 99 | "metadata": { 100 | "needs_background": "light" 101 | }, 102 | "output_type": "display_data" 103 | } 104 | ], 105 | "source": [ 106 | "# easy fix, first save to texts object (Text)\n", 107 | "fig,ax = plt.subplots()\n", 108 | "ax.set_xlim([0,1])\n", 109 | "ax.set_ylim([0,1])\n", 110 | "data_text_coords = (0.9,0.9)\n", 111 | "texts = ax.text(x=data_text_coords[0],y=data_text_coords[1],s='hhhhhhh') # default transform is ax.transData\n", 112 | "plt.pause(0.01)\n", 113 | "ax_text_coords = ax.transAxes.inverted().transform(texts.get_window_extent().get_points())\n", 114 | "# get_window_extent() will return a Bbox object, get_points() for Bbox will return ndarray\n", 115 | "ymax = ax_text_coords[1,1]\n", 116 | "fig,ax = plt.subplots()\n", 117 | "ax.set_xlim([0,ymax+0.3])\n", 118 | "data_text_coords = (0.9,0.9)\n", 119 | "texts = ax.text(x=data_text_coords[0],y=data_text_coords[1],s='hhhhhhh') # default transform is ax.transData" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "id": "8c2ba27f-d970-4191-ba6e-50304d9391d8", 125 | "metadata": {}, 126 | "source": [ 127 | "## More complex fix\n", 128 | "1. make sure the text are drawn based on fig coords\n", 129 | "2. then update the ax based on fig coords" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 16, 135 | "id": "00c728c4-a3af-41e4-a5e2-59fe00697463", 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "data": { 140 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAdIAAAE2CAYAAADVtROiAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAQ8ElEQVR4nO3df6zd9X3f8dfbgIMWUphqV6owFKKZUQcWQq48L5VSJrLIoMhEaVaBEnVUCEssVNMaNWJiShv6V9esQ43YUkeLWCs1/IpUWakrJrUgElQSTAgkdkLjuSQYUIA0RcpP6uy9P+4tulyufY/9Odc+13s8pCOd7/d8zvd8+OjaT3/POfdLdXcAgOOz7mRPAADWMiEFgAFCCgADhBQABggpAAwQUgAYsGJIq+rTVfVCVX3tCI9XVf1hVR2oqier6vLpTxMAZtMkZ6R3Jtl+lMevSrJ54bYzyf8YnxYArA0rhrS7H0ryd0cZck2SP+55jyQ5p6p+floTBIBZNo3PSM9N8syi7UML+wDglHf6iXyxqtqZ+bd/88Y3vvHtF1988Yl8eQBY1mOPPfZSd288nudOI6TPJjlv0famhX2v0927kuxKkrm5ud67d+8UXh4AxlTVt473udN4a3d3kl9b+PbutiQvd/fzUzguAMy8Fc9Iq+ozSa5IsqGqDiX57SRnJEl3fzLJniRXJzmQ5IdJfn21JgsAs2bFkHb3dSs83kk+NLUZAcAa4spGADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAZMFNKq2l5VT1XVgaq6ZZnHz6+qB6rq8ap6sqqunv5UAWD2rBjSqjotyR1JrkqyJcl1VbVlybD/nOSe7n5bkmuT/PdpTxQAZtEkZ6Rbkxzo7oPd/UqSu5Jcs2RMJ/mZhftnJ3luelMEgNl1+gRjzk3yzKLtQ0n+5ZIxv5Pkf1fVbyR5Y5J3TWV2ADDjpvVlo+uS3Nndm5JcneRPqup1x66qnVW1t6r2vvjii1N6aQA4eSYJ6bNJzlu0vWlh32I3JLknSbr7r5OcmWTD0gN1967unuvuuY0bNx7fjAFghkwS0keTbK6qC6tqfea/TLR7yZhvJ7kySarqFzMfUqecAJzyVgxpdx9OcnOS+5N8PfPfzt1XVbdV1Y6FYR9OcmNVPZHkM0mu7+5erUkDwKyY5MtG6e49SfYs2ffRRff3J/ml6U4NAGafKxsBwAAhBYABQgoAA4QUAAYIKQAMEFIAGCCkADBASAFggJACwAAhBYABQgoAA4QUAAYIKcCEnn766VxyySWv23/FFVdk7969r9t/55135uabb172WGeddday+6+//vrcd999r9v/4IMP5j3vec+yz7ngggvy0ksvHW3qrCIhBYABQgpwDH7605/mxhtvzFve8pa8+93vzo9+9KMkyb333putW7fmoosuyuc///lXxz/33HPZvn17Nm/enI985COvOdatt96at771rdm2bVu+853vvLr/oYceyjve8Y68+c1vfs3Z6fe///28//3vz8UXX5wPfOADWfy/ff7EJz6Ryy+/PJdeemm+8Y1vrNZ/PssQUoBj8M1vfjMf+tCHsm/fvpxzzjn57Gc/myQ5fPhwvvSlL+X222/Pxz72sVfHf+UrX8ndd9+dr371q7n77rvzzDPPJEl+8IMfZNu2bXniiSfyzne+M5/61Kdefc7zzz+fL3zhC/nc5z6XW2655dX9jz/+eG6//fbs378/Bw8ezMMPP/zqYxs2bMiXv/zl3HTTTfn4xz++2svAIkIKcAwuvPDCXHbZZUmSt7/97Xn66aeTJO973/tety9Jrrzyypx99tk588wzs2XLlnzrW99Kkqxfv/7VzzyXPue9731v1q1bly1btrzmTHXr1q3ZtGlT1q1bl8suu+w1zznS67P6hBTgGLzhDW949f5pp52Ww4cPv2b/4n1HG3/GGWekqlZ8zuK3b490rKO9PqtPSAFggJACwIBa/LbBiTQ3N9fL/d4VAJxoVfVYd88dz3OdkQLAACEFgAFCCgADhBQABggpAAwQUgAYIKQAMEBIAWCAkALAACEFgAFCCgADhBQABggpAAwQUgAYIKQAMEBIAWCAkALAACEFgAFCCgADhBQABggpAAwQUgAYIKQAMEBIAWCAkALAgIlCWlXbq+qpqjpQVbccYcyvVtX+qtpX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\n", 141 | "text/plain": [ 142 | "
" 143 | ] 144 | }, 145 | "metadata": { 146 | "needs_background": "light" 147 | }, 148 | "output_type": "display_data" 149 | } 150 | ], 151 | "source": [ 152 | "fig,ax = plt.subplots()\n", 153 | "ax.set_xlim([0,1])\n", 154 | "ax.set_ylim([0,1])\n", 155 | "data_text_coords = (0.9,0.9)\n", 156 | "display_text_coords = ax.transData.transform(data_text_coords)\n", 157 | "fig_text_coords = fig.transFigure.inverted().transform(display_text_coords)\n", 158 | "texts = ax.text(x=fig_text_coords[0],y=fig_text_coords[1],s='hhhhhhh',transform=fig.transFigure)\n", 159 | "fig_ax_coords = ax.get_position().get_points()\n", 160 | "## build Bbox from the construct, not extents nor bounds\n", 161 | "new_bbox = Bbox([[fig_ax_coords[0,0],fig_ax_coords[0,1]],[fig_ax_coords[1,0]+0.2,fig_ax_coords[1,1]+0.2]])\n", 162 | "ax.set_position(new_bbox)" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "id": "92ffc797-e7fc-4e40-bd29-26e61decb970", 168 | "metadata": {}, 169 | "source": [ 170 | "# talks a bit about bbox" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 5, 176 | "id": "087abffa-1ecc-4b05-b7d2-730bd40a9a57", 177 | "metadata": {}, 178 | "outputs": [ 179 | { 180 | "data": { 181 | "text/plain": [ 182 | "Bbox([[0.0, 0.0], [1.0, 1.0]])" 183 | ] 184 | }, 185 | "execution_count": 5, 186 | "metadata": {}, 187 | "output_type": "execute_result" 188 | } 189 | ], 190 | "source": [ 191 | "# method1: constructor, [[x0,y0],[x1,y1]], first is the lower left, second is the upper right\n", 192 | "Bbox([[0,0],[1,1]])" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 8, 198 | "id": "aeb6e99d-5155-47e1-b22e-ec6a5652fb65", 199 | "metadata": {}, 200 | "outputs": [ 201 | { 202 | "data": { 203 | "text/plain": [ 204 | "Bbox([[0.0, 0.0], [1.0, 1.0]])" 205 | ] 206 | }, 207 | "execution_count": 8, 208 | "metadata": {}, 209 | "output_type": "execute_result" 210 | } 211 | ], 212 | "source": [ 213 | "# method2: from_bounds(x0,y0,width,height)\n", 214 | "Bbox.from_bounds(0,0,1,1)" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": 10, 220 | "id": "514ed90e-31c5-49b3-b0b1-75dd12d2a225", 221 | "metadata": {}, 222 | "outputs": [ 223 | { 224 | "data": { 225 | "text/plain": [ 226 | "Bbox([[0.0, 0.0], [1.0, 1.0]])" 227 | ] 228 | }, 229 | "execution_count": 10, 230 | "metadata": {}, 231 | "output_type": "execute_result" 232 | } 233 | ], 234 | "source": [ 235 | "# method3: from_extent (x0,y0,y0,y1)\n", 236 | "Bbox.from_extents(0,0,1,1)" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "id": "8fcf1778-c43f-4ee1-a3ab-c6d091cfc51f", 243 | "metadata": {}, 244 | "outputs": [], 245 | "source": [] 246 | } 247 | ], 248 | "metadata": { 249 | "kernelspec": { 250 | "display_name": "Python 3", 251 | "language": "python", 252 | "name": "python3" 253 | }, 254 | "language_info": { 255 | "codemirror_mode": { 256 | "name": "ipython", 257 | "version": 3 258 | }, 259 | "file_extension": ".py", 260 | "mimetype": "text/x-python", 261 | "name": "python", 262 | "nbconvert_exporter": "python", 263 | "pygments_lexer": "ipython3", 264 | "version": "3.6.13" 265 | } 266 | }, 267 | "nbformat": 4, 268 | "nbformat_minor": 5 269 | } 270 | -------------------------------------------------------------------------------- /examples/gridspec.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "import matplotlib\n", 11 | "import matplotlib.pyplot as plt" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 4, 17 | "metadata": {}, 18 | "outputs": [ 19 | { 20 | "data": { 21 | "image/png": "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\n", 22 | "text/plain": [ 23 | "
" 24 | ] 25 | }, 26 | "metadata": { 27 | "needs_background": "light" 28 | }, 29 | "output_type": "display_data" 30 | } 31 | ], 32 | "source": [ 33 | "fig = plt.figure()\n", 34 | "gs = matplotlib.gridspec.GridSpec(nrows=3,ncols=2,width_ratios=(0.1,0.9),height_ratios=(0.1,0.2,0.7),hspace=0.5)\n", 35 | "ax1 = fig.add_subplot(gs[0,1])\n", 36 | "ax2 = fig.add_subplot(gs[1,1])\n", 37 | "ax3 = fig.add_subplot(gs[2,1])\n", 38 | "ax4 = fig.add_subplot(gs[2,0])" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 10, 44 | "metadata": {}, 45 | "outputs": [ 46 | { 47 | "data": { 48 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAD8CAYAAAB0IB+mAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAXwklEQVR4nO3dXahc9b3G8e9j0ljM8Y0mgsTYKI3GTVpoHGx6UxVtiblILiySgGhKatDWFk4PBwQvWuxVObQFOeHoPm1QC41RL2S3KtIXJSBu6w5qNCnKNvVlW2niS3MupNGc/s7FWjVzdvd2/lmzZq09838+MLDWzJqZ32/N7GevWWvNfxQRmJnZ6Dul7QLMzKwZDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48PsgaZekw5JearsWM7NeHPj9uQfY0HYRZmYpHPh9iIi9wHtt12FmlmJx2wWMOkk7gB0AS5cuvXTNmjUtV2Rmw2zfvn3vRMTyKvd14A9YRIwD4wCdTiempqZarsjMhpmk16ve17t0zMwy4cA3M8uEA78PknYDTwMXS5qRtL3tmszM5uPA78+9wP8ArwP/GRE/b7keM7N5OfArkrQI2AlcA4wBWyWNtVuVmdn8HPjVXQZMR8ShiPgQuB/Y3HJNZmbz8mmZ1a0A3uyanwG+NHuh7vPwgWMjPAzDMuCdtosYkFHtbVT7gtHu7eKqd3TgD1j3efiSpiKi03JJA+Hehs+o9gWj31vV+3qXTnVvASu75s8rrzMzW5Ac+NU9C6yWdIGkJcAWYKLlmszM5uVdOhVFxHFJtwKPA4uAXRFxoMfdxgdfWWvc2/AZ1b7Avc1JEVFnIWZmtkB5l46ZWSYc+GZmmXDgD4CkDZJeljQt6bY5bj9V0p7y9mckrWqhzJOW0Nf3JB2UtF/S7yR9to06q+jVW9dy10oKSUNzyl9Kb5KuK1+7A5J+2XSNVSW8J8+X9ISk58r35cY26jxZvX4+VYU7y773S1qX9MAR4UuNF4oDuK8CFwJLgBeAsVnLfAu4q5zeAuxpu+6a+roSOK2cvmUY+krtrVzudGAvMAl02q67xtdtNfAccHY5f07bddfY2zhwSzk9BrzWdt2JvX0FWAe8NM/tG4HHAAHrgWdSHtdb+PVLGXJhM8XAawAPAVdJUoM1VtGzr4h4IiI+KGcnKb6bMAxSh8n4IfAj4G9NFtenlN5uAnZGxPsAEXG44RqrSuktgDPK6TOBPzdYX2XR++dTNwP3RWESOEvSub0e14Ffv7mGXFgx3zIRcRw4CnymkeqqS+mr23aKLZBh0LO38iPzyoh4pMnCapDyul0EXCTpKUmTkjY0Vl1/Unr7AXC9pBngUeA7zZQ2cCf79wj4PHwbAEnXAx3g8rZrqYOkU4CfANtaLmVQFlPs1rmC4lPZXkmfj4i/tllUTbYC90TEjyV9GfiFpLUR8fe2C2uDt/DrlzLkwsfLSFpM8VHz3Uaqqy5pKAlJVwO3A5si4lhDtfWrV2+nA2uBJyW9RrHPdGJIDtymvG4zwEREfBQRfwJeofgHsNCl9LYdeAAgIp4GPk0xsNqwqzS0iwO/D/McSU8ZcmECuLGc/jrw+yiPxCxgPfuS9EXgboqwH5b9wNCjt4g4GhHLImJVRKyiOD6xKSKG4RfpU96PD1Ns3SNpGcUunkMN1lhVSm9vAFcBSLqEIvCPNFrlYEwAN5Rn66wHjkbE2z3v1fbR6GG+MM+RdIoj6K9QnEFwe3ndHRQhAcWb7kFgGvgDcGHbvST226uv3wJ/AZ4vLxNt11xXb7OWfZIhOUsn8XUTxS6rg8CLwJa2a66xtzHgKYozeJ4HvtZ2zYl97QbeBj6i+AS2HbgZuLnrNdtZ9v1i6vvRQyv0qTyH/tcRsbbtWszMPokP2g5Y9w+gLF269NI1a9a0XJGZDbN9+/a9ExHLq9zXgT9g0fUDKJ1OJ6amhmG3r5ktVJJer3pfH7Q1M8uEA9/MLBMO/D5I2g08DVwsaUbS9rZrMjObj/fh9yEitrZdg5lZKm/hm5llwoFvZpYJB76ZWSYc+GZmmXDgm5llwoFvZpYJB34fUn/42sxsIXDgVyRpEcXwpNdQDMG6VdJYu1WZmc3PgV9d6g9fm5ktCP6mbXVz/Yjwl2Yv1D08MnBs1q9jjZJlwDttFzEgo9rbqPYFo93bxVXv6MAfsO7hkSVNRcQw/A7qSXNvw2dU+4LR763qfb1Lp7pKPyJsZtYWB351KT+gbGa2YHiXTkURcVzSrcDjwCJgV0Qc6HG38cFX1hr3NnxGtS9wb3Pyj5ibmWXCu3TMzDLhwDczy4QDfwB6Dbkg6VRJe8rbn5G0qoUyT1pCX9+TdFDSfkm/k/TZNuqsInWYDEnXSgpJQ3PKX0pvkq4rX7sDkn7ZdI1VJbwnz5f0hKTnyvflxjbqPFmSdkk6PN/3dlS4s+x7v6R1SQ8cEb7UeKE4gPsqcCGwBHgBGJu1zLeAu8rpLcCetuuuqa8rgdPK6VuGoa/U3srlTgf2ApNAp+26a3zdVgPPAWeX8+e0XXeNvY0Dt5TTY8Brbded2NtXgHXAS/PcvhF4DBCwHngm5XG9hV+/lCEXNgP3ltMPAVdJUoM1VtGzr4h4IiI+KGcnKb6bMAxSh8n4IfAj4G9NFtenlN5uAnZGxPsAEXG44RqrSuktgDPK6TOBPzdYX2URsRd47xMW2QzcF4VJ4CxJ5/Z6XAd+/eYacmHFfMtExHHgKPCZRqqrLqWvbtsptkCGQc/eyo/MKyPikSYLq0HK63YRcJGkpyRNStrQWHX9SentB8D1kmaAR4HvNFPawJ3s3yPg8/BtACRdD3SAy9uupQ6STgF+AmxruZRBWUyxW+cKik9leyV9PiL+2mZRNdkK3BMRP5b0ZeAXktZGxN/bLqwN3sKvX8qQCx8vI2kxxUfNdxuprrqkoSQkXQ3cDmyKiGMN1davXr2dDqwFnpT0GsU+04khOXCb8rrNABMR8VFE/Al4heIfwEKX0tt24AGAiHga+DTFwGrDrtLQLj0Df2BHixewPntOGXJhArixnP468Psoj8QsYD37kvRF4G6KsB+W/cDQo7eIOBoRyyJiVUSsojg+sSkiKg9i1aCU9+PDFFv3SFpGsYvnUIM1VpXS2xvAVQCSLqEI/CONVjkYE8ANZRatB45GxNs979XW0eKFfOm35/L2VyjOILi9vO4OipCA4k33IDAN/AG4sO2eE9dLr75+C/wFeL68TLRdc129zVr2SYbkLJ3E100Uu6wOAi8CW9quucbexoCnKM7geR74Wts1J/a1G3gb+IjiE9h24Gbg5q7XbGfZ94up78ekoRXK88R/HRFr57jtbuDJiNhdzr8MXBEp/20WsBx7NrPRVsc+/EpHi4dcjj2b2ZBr9Cwddf3609KlSy9ds2ZNk0//sX379r0TEcubeK6F0rOZjYZ+8quOwE8+Whxdv/7U6XRiaqqdY16SXu/zIYauZzMbDf3kVx27dKodLR5uOfZsZkOu5xa+pN0Up2wtK7+t9n3gUwARcRfFt9c2Upxx8gHwjUEV25Qcezaz0dcz8CNia4/bA/h2bRUtADn2bGajz9+0NTPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTSYEvaYOklyVNS7ptjtu3SToi6fny8s36S21Wjj2b2WhL+RHzRcBO4KvADPCspImIODhr0T0RcesAamxcjj2b2ehL2cK/DJiOiEMR8SFwP7B5sGW1LseezWzEpQT+CuDNrvmZ8rrZrpW0X9JDklbO9UCSdkiakjR15MiRCuU2JseezWzE1XXQ9lfAqoj4AvAb4N65FoqI8YjoRERn+fLlNT11a3Ls2cyGWErgvwV0b72eV173sYh4NyKOlbM/Ay6tp7zW5NizmY24lMB/Flgt6QJJS4AtwET3ApLO7ZrdBPyxvhJbkWPPZjbiep6lExHHJd0KPA4sAnZFxAFJdwBTETEBfFfSJuA48B6wbYA1D1yOPZvZ6FNEtPLEnU4npqamWnluSfsiotP087bZs5mNhn7yy9+0NTPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLRFLgS9og6WVJ05Jum+P2UyXtKW9/RtKq2ittWI49m9lo6xn4khYBO4FrgDFgq6SxWYttB96PiM8BPwV+VHehTcqxZzMbfSlb+JcB0xFxKCI+BO4HNs9aZjNwbzn9EHCVJNVXZuNy7NnMRtzihGVWAG92zc8AX5pvmYg4Luko8Bngne6FJO0AdpSzxyS9VKXoGlzc4/ZR7HnQljGr9xEyqr2Nal8w2r31yq95pQR+bSJiHBgHkDRV9ZfX+yVpqqnnWig9D5p7Gz6j2heMfm9V75uyS+ctYGXX/HnldXMuI2kxcCbwbtWiFoAcezazEZcS+M8CqyVdIGkJsAWYmLXMBHBjOf114PcREfWV2bgcezazEddzl065f/pW4HFgEbArIg5IugOYiogJ4OfALyRNA+9RBGQv433U3a9PfO4R7XnQ3NvwGdW+wL3NSd4oNTPLg79pa2aWCQe+mVkmWgn8XsMWDOg5d0k63MR58KM6LENCX9+TdFDSfkm/k/TZNuqsIvU9KelaSSFpaE75S+lN0nXla3dA0i+brrGqhPfk+ZKekPRc+b7c2EadJ6tXXqlwZ9n3fknrkh44Ihq9UBwEfRW4EFgCvACMNfC8XwHWAS+13R/wLeCucnoLsKfp12FAfV0JnFZO3zIMfaX2Vi53OrAXmAQ6bddd4+u2GngOOLucP6ftumvsbRy4pZweA15ru+7E3j4xr4CNwGOAgPXAMymP28YWfsqwBbWLiL0UZ9MM2qgOy9Czr4h4IiI+KGcnKb6/MAxS35M/pBgz6W9NFtenlN5uAnZGxPsAEXG44RqrSuktgDPK6TOBPzdYX2UJebUZuC8Kk8BZks7t9bhtBP5cwxasaKGOQUnp7/8NywD8Y1iGhexkX7ftFFsgw6Bnb+VH5pUR8UiThdUg5XW7CLhI0lOSJiVtaKy6/qT09gPgekkzwKPAd5opbeAq5WijQytYHiRdD3SAy9uupQ6STgF+AmxruZRBWUyxW+cKik9leyV9PiL+2mZRNdkK3BMRP5b0ZYrvzqyNiL+3XVgb2tjCTxm2YJiN6rAMSa+bpKuB24FNEXGsodr61au304G1wJOSXqPYZzoxJAduU163GWAiIj6KiD8Br1D8A1joUnrbDjwAEBFPA5+mGFht2FXK0TYCP2XYgmE2qsMy9OxL0heBuynCflj2A0OP3iLiaEQsi4hVEbGK4vjEpohobBC+PqS8Hx+m2LpH0jKKXTyHGqyxqpTe3gCuApB0CUXgH2m0ysGYAG4oz9ZZDxyNiLd73qulI9AbKbYiXgVub+g5dwNvAx9RbNFsb7I/4A6KkIDiTfcgMA38AbiwjddhAH39FvgL8Hx5mWi75rp6m7XskwzJWTqJr5sodlkdBF4EtrRdc429jQFPUZzB8zzwtbZrTuzrn/IKuBm4ues121n2/WLq+9FDK5iZZcLftDUzy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy0TPwJe0S9JhSS/Nc7sk3SlpWtJ+SevqL9PMzPqVsoV/D7DhE26/BlhdXnYA/9V/WWZmVreegR8Re4H3PmGRzcB9UZgEzpJ0bl0FmplZPRbX8BgrgDe75mfK696evaCkHRSfAli6dOmla9asqeHpzczysW/fvnciYnmV+9YR+MkiYhwYB+h0OjE1NdXk05uZDT1Jr1e9bx1n6bwFrOyaP6+8zszMFpA6An8CuKE8W2c9cDQi/ml3jpmZtavnLh1Ju4ErgGWSZoDvA58CiIi7gEeBjcA08AHwjUEVa2Zm1fUM/IjY2uP2AL5dW0VmZjYQ/qatmVkmHPhmZplw4JuZZcKBb2aWCQe+mVkmHPhmZplw4JuZZcKBb2aWCQe+mVkmHPhmZplw4JuZZcKBb2aWCQe+mVkmHPhmZplw4JuZZcKBb2aWiaTAl7RB0suSpiXdNsft2yQdkfR8eflm/aWamVk/Un7icBGwE/gqMAM8K2kiIg7OWnRPRNw6gBrNzKwGKVv4lwHTEXEoIj4E7gc2D7YsMzOrW0rgrwDe7JqfKa+b7VpJ+yU9JGllLdWZmVlt6jpo+ytgVUR8AfgNcO9cC0naIWlK0tSRI0dqemozM0uREvhvAd1b7OeV130sIt6NiGPl7M+AS+d6oIgYj4hORHSWL19epV4zM6soJfCfBVZLukDSEmALMNG9gKRzu2Y3AX+sr0QzM6tDz7N0IuK4pFuBx4FFwK6IOCDpDmAqIiaA70raBBwH3gO2DbBmMzOrQBHRyhN3Op2Ymppq5bnNzIaVpH0R0alyX3/T1swsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsEw58M7NMOPDNzDLhwDczy4QD38wsE0mBL2mDpJclTUu6bY7bT5W0p7z9GUmraq/UzMz60jPwJS0CdgLXAGPAVkljsxbbDrwfEZ8Dfgr8qO5CzcysPylb+JcB0xFxKCI+BO4HNs9aZjNwbzn9EHCVJNVXppmZ9WtxwjIrgDe75meAL823TEQcl3QU+AzwTvdCknYAO8rZY5JeqlL0CFrGrHWVMa+LE7wuTvC6OOHiqndMCfzaRMQ4MA4gaarqL6+PGq+LE7wuTvC6OMHr4gRJU1Xvm7JL5y1gZdf8eeV1cy4jaTFwJvBu1aLMzKx+KYH/LLBa0gWSlgBbgIlZy0wAN5bTXwd+HxFRX5lmZtavnrt0yn3ytwKPA4uAXRFxQNIdwFRETAA/B34haRp4j+KfQi/jfdQ9arwuTvC6OMHr4gSvixMqrwt5Q9zMLA/+pq2ZWSYc+GZmmRh44HtYhhMS1sX3JB2UtF/S7yR9to06m9BrXXQtd62kkDSyp+SlrAtJ15XvjQOSftl0jU1J+Bs5X9ITkp4r/042tlHnoEnaJenwfN9VUuHOcj3tl7Qu6YEjYmAXioO8rwIXAkuAF4CxWct8C7irnN4C7BlkTW1dEtfFlcBp5fQtOa+LcrnTgb3AJNBpu+4W3xergeeAs8v5c9quu8V1MQ7cUk6PAa+1XfeA1sVXgHXAS/PcvhF4DBCwHngm5XEHvYXvYRlO6LkuIuKJiPignJ2k+M7DKEp5XwD8kGJcpr81WVzDUtbFTcDOiHgfICION1xjU1LWRQBnlNNnAn9usL7GRMReijMe57MZuC8Kk8BZks7t9biDDvy5hmVYMd8yEXEc+MewDKMmZV10207xH3wU9VwX5UfUlRHxSJOFtSDlfXERcJGkpyRNStrQWHXNSlkXPwCulzQDPAp8p5nSFpyTzROg4aEVLI2k64EOcHnbtbRB0inAT4BtLZeyUCym2K1zBcWnvr2SPh8Rf22zqJZsBe6JiB9L+jLF93/WRsTf2y5sGAx6C9/DMpyQsi6QdDVwO7ApIo41VFvTeq2L04G1wJOSXqPYRzkxogduU94XM8BERHwUEX8CXqH4BzBqUtbFduABgIh4Gvg0xcBquUnKk9kGHfgeluGEnutC0heBuynCflT300KPdRERRyNiWUSsiohVFMczNkVE5UGjFrCUv5GHKbbukbSMYhfPoQZrbErKungDuApA0iUUgX+k0SoXhgnghvJsnfXA0Yh4u9edBrpLJwY3LMPQSVwX/wH8C/Bgedz6jYjY1FrRA5K4LrKQuC4eB74m6SDwv8C/R8TIfQpOXBf/Bvy3pH+lOIC7bRQ3ECXtpvgnv6w8XvF94FMAEXEXxfGLjcA08AHwjaTHHcF1ZWZmc/A3bc3MMuHANzPLhAPfzCwTDnwzs0w48M3MMuHANzPLhAPfzCwT/wdJY61yTYY/zQAAAABJRU5ErkJggg==\n", 49 | "text/plain": [ 50 | "
" 51 | ] 52 | }, 53 | "metadata": { 54 | "needs_background": "light" 55 | }, 56 | "output_type": "display_data" 57 | } 58 | ], 59 | "source": [ 60 | "fig = plt.figure()\n", 61 | "gs = matplotlib.gridspec.GridSpec(nrows=3,ncols=2,width_ratios=(0.1,0.9),height_ratios=(0.1,0.2,0.7),hspace=0.7)\n", 62 | "ax1 = fig.add_subplot(gs[0,1])\n", 63 | "ax2 = fig.add_subplot(gs[1,1])\n", 64 | "ax3 = fig.add_subplot(gs[2,1])\n", 65 | "ax4 = fig.add_subplot(gs[2,0])\n", 66 | "gs.update(bottom=0.5)\n", 67 | "gs2 = matplotlib.gridspec.GridSpec(nrows=1,ncols=1,top=0.3)\n", 68 | "ax5 = fig.add_subplot(gs2[0,0])" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [] 77 | } 78 | ], 79 | "metadata": { 80 | "kernelspec": { 81 | "display_name": "Python 3", 82 | "language": "python", 83 | "name": "python3" 84 | }, 85 | "language_info": { 86 | "codemirror_mode": { 87 | "name": "ipython", 88 | "version": 3 89 | }, 90 | "file_extension": ".py", 91 | "mimetype": "text/x-python", 92 | "name": "python", 93 | "nbconvert_exporter": "python", 94 | "pygments_lexer": "ipython3", 95 | "version": "3.6.12" 96 | } 97 | }, 98 | "nbformat": 4, 99 | "nbformat_minor": 4 100 | } 101 | -------------------------------------------------------------------------------- /examples/legend.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "import matplotlib\n", 11 | "import matplotlib.pyplot as plt\n", 12 | "import matplotlib.patches as mpatches\n", 13 | "import matplotlib.lines as mlines" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 4, 19 | "metadata": {}, 20 | "outputs": [ 21 | { 22 | "data": { 23 | "text/plain": [ 24 | "" 25 | ] 26 | }, 27 | "execution_count": 4, 28 | "metadata": {}, 29 | "output_type": "execute_result" 30 | }, 31 | { 32 | "data": { 33 | "image/png": "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\n", 34 | "text/plain": [ 35 | "
" 36 | ] 37 | }, 38 | "metadata": { 39 | "needs_background": "light" 40 | }, 41 | "output_type": "display_data" 42 | } 43 | ], 44 | "source": [ 45 | "# a patch of color\n", 46 | "fig,ax = plt.subplots()\n", 47 | "ax.legend(handles=[mpatches.Patch(color=i) for i in 'rgb'],labels=['red','green','blue'])" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 5, 53 | "metadata": {}, 54 | "outputs": [ 55 | { 56 | "data": { 57 | "text/plain": [ 58 | "" 59 | ] 60 | }, 61 | "execution_count": 5, 62 | "metadata": {}, 63 | "output_type": "execute_result" 64 | }, 65 | { 66 | "data": { 67 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAD8CAYAAAB0IB+mAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAUi0lEQVR4nO3dfYxW9Z338fcXYToBfLgjKBNBxdyAIEXAwRUhyp22PqUd2mhVUmOlZjHSbppqd2vjbTWaJt22u3djQ2/FSGzXuj7QVNF1o+lWY3zAOsSHCJSVut46rtSRddUJHWHke/9xXcIwAnM5c80D/N6vZDLn/M7vOuc7v8x85sw55/pNZCaSpIPfiKEuQJI0OAx8SSqEgS9JhTDwJakQBr4kFcLAl6RC9Br4EbEqIt6OiJf3sT0i4uaI2BwRL0XE3PqXKUnqr1rO8O8AztnP9nOBKdWPZcD/7X9ZkqR66zXwM/MJ4L/202Ux8KusWAscERFN9SpQklQfI+uwj2OAN7qtt1Xb3urZMSKWUfkrgDFjxpxy4okn1uHwklSOdevWvZOZ4/vy2noEfs0ycyWwEqC5uTlbW1sH8/CSdMCLiP/X19fW4ymdN4FJ3dYnVtskScNIPQJ/DXBp9Wmd04D3MvMTl3MkSUOr10s6EfHPwCJgXES0AdcDowAy8xbgYeA8YDOwDVg6UMVKkvqu18DPzCW9bE/gm3WrSJKAHTt20NbWRmdn51CXMiQaGxuZOHEio0aNqts+B/WmrSTVqq2tjUMPPZTjjz+eiBjqcgZVZrJ161ba2tqYPHly3fbr1AqShqXOzk6OPPLI4sIeICI48sgj6/7XjYEvadgqMew/NhBfu4EvSYUw8CWpjm644QZ++tOfDnUZe2XgSzrwzZkDEZ/8mDOnbofITHbu3Fm3/Q0FA1/SgW/+fGho2LOtoQFOP71fu33ttdeYNm0al156KTNnzuSmm25i3rx5zJo1i+uvv35Xvx/+8IdMnTqVhQsXsmnTpn4dcyD5WKakA8OiRZ9su/BCWL4crr4abr11z21dXTB1amX5nXfgggv23P744zUd9pVXXuGXv/wl77//PqtXr+YPf/gDmUlLSwtPPPEEY8aM4e677+aFF16gq6uLuXPncsopp3zqL28wGPiSDnxNTXD00bBlC2RWLudMmACHH97vXR933HGcdtppfPe73+XRRx9lTvUyUUdHB6+88goffPABX/nKVxg9ejQALS0t/T7mQDHwJR0Y9ndGPno0rFsHJ5wAnZ3Q2FhZnzChsn3cuJrP6HsaM2YMULmG//3vf58rrrhij+0/+9nP+rTfoeA1fEkHh6YmWLoURoyofP447Ovk7LPPZtWqVXR0dADw5ptv8vbbb3PGGWdw//3385e//IUPPviABx98sK7HrSfP8CUdPK67Dtavr3yus7POOouNGzcyf/58AMaOHcudd97J3Llzueiiizj55JM56qijmDdvXt2PXS9Rmfts8PkPUCTtz8aNG5k+ffpQlzGk9jYGEbEuM5v7sj8v6UhSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAjfeCXpgDfn1jm8sOWFT7TPnjCb5694fkCP3dXVxciRB0aUHhhVStJ+zJ84nw3tG9j+0fZdbQ2HNHD6xP5Njwxw0003ceeddzJ+/HgmTZrEKaecwkMPPcTs2bN58sknWbJkCYsWLeKqq66io6ODcePGcccdd9DU1MSf/vQnvvnNb9Le3s7o0aO57bbbOPHEE7nssss47LDDaG1tZcuWLfz4xz/mgp6zeQ4AA1/SAWHRHYs+0XbhSReyfN5yrj79am5dt+f0yF07u5h6ZGV65He2vcMF9+4ZqI9f9nivx3zuuef4zW9+w4svvsiOHTv2mPp4+/bttLa2smPHDs4880weeOABxo8fzz333MO1117LqlWrWLZsGbfccgtTpkzh2WefZfny5fz+978H4K233uLJJ5/kj3/8Iy0tLQa+JNWiaWwTR485mi0dW0iSIJgwZgKHN/ZveuSnnnqKxYsX09jYSGNjI1/60pd2bbvooosA2LRpEy+//DJf+MIXAPjoo49oamqio6ODp59+mq9+9au7XvPhhx/uWv7yl7/MiBEjmDFjBn/+85/7VWetDHxJB4T9nZGPHjWadcvWccLNJ9DZ1UnjyEbWXbGOCWMrM2aOGz2upjP6T6P7tMknnXQSzzzzzB7b33//fY444gheeOGFvb7+M5/5zK7lwZrTzKd0JB0Umg5tYunspYyIESydvXRX2PfHggULePDBB+ns7KSjo4OHHnroE32mTZtGe3v7rsDfsWMH69ev57DDDmPy5Mncd999QCXUX3zxxX7X1B8GvqSDxnVnXMfCYxdy3Zn1mR553rx5tLS0MGvWLM4991w++9nPcniP/6LV0NDA6tWr+d73vsfJJ5/M7NmzefrppwH49a9/ze23387JJ5/MSSedxAMPPFCXuvrK6ZElDUvDZXrkjo4Oxo4dy7Zt2zjjjDNYuXIlc+fOHZRj13t6ZK/hS9J+LFu2jA0bNtDZ2cnXv/71QQv7gWDgS9J+3HXXXUNdQt14DV+SCmHgS1IhDHxJKoSBL0mFMPAlaR9ee+01Zs6c+Yn2RYsWcSA+Vl5T4EfEORGxKSI2R8Q1e9l+bEQ8FhHPR8RLEXFe/UuVpL2bMwciPvkxZ85QVza89Br4EXEIsAI4F5gBLImIGT26/W/g3sycA1wM/KLehUrSvsyfDw0Ne7Y1NMDp/Z8dma6uLr72ta8xffp0LrjgArZt27bH9rFjx+5aXr16NZdddhkA7e3tnH/++cybN4958+bx1FNP9b+YfqrlOfxTgc2Z+SpARNwNLAY2dOuTwGHV5cOB/6xnkZK0aNEn2y68EJYvh6uvhlv3nB2Zri6YWpkdmXfegZ6zDz/+eG3H3bRpE7fffjsLFizgG9/4Br/4RW3ns9/+9rf5zne+w8KFC3n99dc5++yz2bhxY20HHSC1BP4xwBvd1tuAv+rR5wbg0Yj4G2AM8Pm97SgilgHLAI499thPW6sk7VVTExx9NGzZApmVyzkTJsDh/ZsdGYBJkyaxYMECAC655BJuvvnmml73u9/9jg0bdp8Xv//++7umaRgq9Xqn7RLgjsz8h4iYD/xTRMzMzJ3dO2XmSmAlVObSqdOxJRVgf2fko0fDunVwwgnQ2QmNjZX1CdUJM8eNq/2MvqeIqHm9s7Nz1/LOnTtZu3YtjY2NfTvwAKjlpu2bwKRu6xOrbd1dDtwLkJnPAI3AuHoUKEm1aGqCpUthxIjK5wn9nx0ZgNdff33X1Md33XUXCxcu3GP70UcfzcaNG9m5cye//e1vd7WfddZZ/PznP9+1vq958QdTLYH/HDAlIiZHRAOVm7JrevR5HfgcQERMpxL47fUsVJJ6c911sHBh5XO9TJs2jRUrVjB9+nTeffddrrzyyj22/+hHP+KLX/wip59+Ok1NTbvab775ZlpbW5k1axYzZszglltuqV9RfVTT9MjVxyx/BhwCrMrMH0bEjUBrZq6pPrVzGzCWyg3cv8vMR/e3T6dHlrQ/w2V65KE0JNMjZ+bDwMM92n7QbXkDsKAvBUiSBofvtJWkQhj4koatofqPfMPBQHztBr6kYamxsZGtW7cWGfqZydatW+v+SKf/8UrSsDRx4kTa2tpoby/zgb/GxkYmTpxY130a+JKGpVGjRjF58uShLuOg4iUdSSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RC1BT4EXFORGyKiM0Rcc0++lwYERsiYn1E3FXfMiVJ/TWytw4RcQiwAvgC0AY8FxFrMnNDtz5TgO8DCzLz3Yg4aqAKliT1TS1n+KcCmzPz1czcDtwNLO7R56+BFZn5LkBmvl3fMiVJ/VVL4B8DvNFtva3a1t1UYGpEPBURayPinL3tKCKWRURrRLS2t7f3rWJJUp/U66btSGAKsAhYAtwWEUf07JSZKzOzOTObx48fX6dDS5JqUUvgvwlM6rY+sdrWXRuwJjN3ZOZ/AP9O5ReAJGmYqCXwnwOmRMTkiGgALgbW9OhzP5WzeyJiHJVLPK/Wr0xJUn/1GviZ2QV8C3gE2Ajcm5nrI+LGiGipdnsE2BoRG4DHgL/NzK0DVbQk6dOLzBySAzc3N2dra+uQHFuSDlQRsS4zm/vyWt9pK0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFaKmwI+IcyJiU0Rsjohr9tPv/IjIiGiuX4mSpHroNfAj4hBgBXAuMANYEhEz9tLvUODbwLP1LlKS1H+1nOGfCmzOzFczcztwN7B4L/1uAv4e6KxjfZKkOqkl8I8B3ui23lZt2yUi5gKTMvNf9rejiFgWEa0R0dre3v6pi5Uk9V2/b9pGxAjgH4Gre+ubmSszszkzm8ePH9/fQ0uSPoVaAv9NYFK39YnVto8dCswEHo+I14DTgDXeuJWk4aWWwH8OmBIRkyOiAbgYWPPxxsx8LzPHZebxmXk8sBZoyczWAalYktQnvQZ+ZnYB3wIeATYC92bm+oi4MSJaBrpASVJ9jKylU2Y+DDzco+0H++i7qP9lSZLqzXfaSlIhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSpETYEfEedExKaI2BwR1+xl+1URsSEiXoqIf4uI4+pfqiSpP3oN/Ig4BFgBnAvMAJZExIwe3Z4HmjNzFrAa+HG9C5Uk9U8tZ/inApsz89XM3A7cDSzu3iEzH8vMbdXVtcDE+pYpSeqvWgL/GOCNbutt1bZ9uRz4171tiIhlEdEaEa3t7e21VylJ6re63rSNiEuAZuAne9uemSszszkzm8ePH1/PQ0uSejGyhj5vApO6rU+stu0hIj4PXAucmZkf1qc8SVK91HKG/xwwJSImR0QDcDGwpnuHiJgD3Aq0ZObb9S9TktRfvQZ+ZnYB3wIeATYC92bm+oi4MSJaqt1+AowF7ouIFyJizT52J0kaIrVc0iEzHwYe7tH2g27Ln69zXZKkOvOdtpJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiEMfEkqhIEvSYUw8CWpEAa+JBXCwJekQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRAGviQVwsCXpEIY+JJUCANfkgph4EtSIQx8SSqEgS9JhTDwJakQBr4kFcLAl6RCGPiSVAgDX5IKYeBLUiFqCvyIOCciNkXE5oi4Zi/bPxMR91S3PxsRx9e9UklSv/Qa+BFxCLACOBeYASyJiBk9ul0OvJuZ/xP4P8Df17tQSVL/1HKGfyqwOTNfzcztwN3A4h59FgO/rC6vBj4XEVG/MiVJ/TWyhj7HAG90W28D/mpffTKzKyLeA44E3uneKSKWAcuqqx9GxMt9KfogNI4eY1Uwx2I3x2I3x2K3aX19YS2BXzeZuRJYCRARrZnZPJjHH64ci90ci90ci90ci90iorWvr63lks6bwKRu6xOrbXvtExEjgcOBrX0tSpJUf7UE/nPAlIiYHBENwMXAmh591gBfry5fAPw+M7N+ZUqS+qvXSzrVa/LfAh4BDgFWZeb6iLgRaM3MNcDtwD9FxGbgv6j8UujNyn7UfbBxLHZzLHZzLHZzLHbr81iEJ+KSVAbfaStJhTDwJakQAx74TsuwWw1jcVVEbIiIlyLi3yLiuKGoczD0Nhbd+p0fERkRB+0jebWMRURcWP3eWB8Rdw12jYOlhp+RYyPisYh4vvpzct5Q1DnQImJVRLy9r/cqRcXN1XF6KSLm1rTjzBywDyo3ef8EnAA0AC8CM3r0WQ7cUl2+GLhnIGsaqo8ax+J/AaOry1eWPBbVfocCTwBrgeahrnsIvy+mAM8D/6O6ftRQ1z2EY7ESuLK6PAN4bajrHqCxOAOYC7y8j+3nAf8KBHAa8Gwt+x3oM3ynZdit17HIzMcyc1t1dS2V9zwcjGr5vgC4icq8TJ2DWdwgq2Us/hpYkZnvAmTm24Nc42CpZSwSOKy6fDjwn4NY36DJzCeoPPG4L4uBX2XFWuCIiGjqbb8DHfh7m5bhmH31ycwu4ONpGQ42tYxFd5dT+Q1+MOp1LKp/ok7KzH8ZzMKGQC3fF1OBqRHxVESsjYhzBq26wVXLWNwAXBIRbcDDwN8MTmnDzqfNE2CQp1ZQbSLiEqAZOHOoaxkKETEC+EfgsiEuZbgYSeWyziIqf/U9ERGfzcz/HsqihsgS4I7M/IeImE/l/T8zM3PnUBd2IBjoM3ynZditlrEgIj4PXAu0ZOaHg1TbYOttLA4FZgKPR8RrVK5RrjlIb9zW8n3RBqzJzB2Z+R/Av1P5BXCwqWUsLgfuBcjMZ4BGKhOrlaamPOlpoAPfaRl263UsImIOcCuVsD9Yr9NCL2ORme9l5rjMPD4zj6dyP6MlM/s8adQwVsvPyP1Uzu6JiHFULvG8Oog1DpZaxuJ14HMAETGdSuC3D2qVw8Ma4NLq0zqnAe9l5lu9vWhAL+nkwE3LcMCpcSx+AowF7qvet349M1uGrOgBUuNYFKHGsXgEOCsiNgAfAX+bmQfdX8E1jsXVwG0R8R0qN3AvOxhPECPin6n8kh9XvV9xPTAKIDNvoXL/4jxgM7ANWFrTfg/CsZIk7YXvtJWkQhj4klQIA1+SCmHgS1IhDHxJKoSBL0mFMPAlqRD/Hy4+uj3I2OT1AAAAAElFTkSuQmCC\n", 68 | "text/plain": [ 69 | "
" 70 | ] 71 | }, 72 | "metadata": { 73 | "needs_background": "light" 74 | }, 75 | "output_type": "display_data" 76 | } 77 | ], 78 | "source": [ 79 | "# Line2D\n", 80 | "fig,ax = plt.subplots()\n", 81 | "ax.legend(handles=[mlines.Line2D([],[],marker='v',linestyle='--',color=i) for i in 'rgb'],labels=['red','green','blue'])" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "# further explanation of loc and bbox_to_anchors argument.\n", 89 | "\n", 90 | "1. there's a bounding box and a legend box \n", 91 | "2. when bbox_to_anchor is a tuple of length 4 (x0,y0,width,height), the x0,y0 always means the lower left of the bounding box. Then the loc determine how the legend box will align with the bounding box. for instance, upper left means the upper left of the bounding box and the upper left of the legend box are overlapping with each other.\n", 92 | "3. when bbox_to_anchor is a tuple of length 2 (x0,y0), the bounding box is by default a dot (width and height = 0), so it seems like the loc means the \"loc\" of the legend box itself to the (x0,y0) we just specified" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 9, 98 | "metadata": {}, 99 | "outputs": [ 100 | { 101 | "data": { 102 | "image/png": "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\n", 103 | "text/plain": [ 104 | "
" 105 | ] 106 | }, 107 | "metadata": { 108 | "needs_background": "light" 109 | }, 110 | "output_type": "display_data" 111 | }, 112 | { 113 | "data": { 114 | "text/plain": [ 115 | "array([[0.94347372, 0.70198675],\n", 116 | " [1.07004182, 0.92273731]])" 117 | ] 118 | }, 119 | "execution_count": 9, 120 | "metadata": {}, 121 | "output_type": "execute_result" 122 | } 123 | ], 124 | "source": [ 125 | "# How to retrieve the width and height of the legend box\n", 126 | "fig,ax = plt.subplots()\n", 127 | "leg1 = ax.legend(handles=[mpatches.Patch(color=i) for i in 'rgb'],labels=['r','g','b'],loc='upper left',bbox_to_anchor=(1,1))\n", 128 | "plt.pause(0.01) # most importantly!!!!!! doesn't matter which matplotlib backend you are using\n", 129 | "frame = leg1.get_frame() # rectangle, actually fancyboxpath\n", 130 | "x0 = frame.get_x()\n", 131 | "y0 = frame.get_y()\n", 132 | "x1 = x0 + frame.get_width()\n", 133 | "y1 = y0 + frame.get_height()\n", 134 | "ax.transAxes.inverted().transform([[x0,y0],[x1,y1]])" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 5, 140 | "metadata": {}, 141 | "outputs": [ 142 | { 143 | "data": { 144 | "text/plain": [ 145 | "array([[0.94347372, 0.70198675],\n", 146 | " [1.07004182, 0.92273731]])" 147 | ] 148 | }, 149 | "execution_count": 5, 150 | "metadata": {}, 151 | "output_type": "execute_result" 152 | } 153 | ], 154 | "source": [ 155 | "# alternatively\n", 156 | "frame = leg1.get_frame()\n", 157 | "ax.transAxes.inverted().transform(frame.get_bbox().get_points())" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [] 166 | } 167 | ], 168 | "metadata": { 169 | "kernelspec": { 170 | "display_name": "Python 3", 171 | "language": "python", 172 | "name": "python3" 173 | }, 174 | "language_info": { 175 | "codemirror_mode": { 176 | "name": "ipython", 177 | "version": 3 178 | }, 179 | "file_extension": ".py", 180 | "mimetype": "text/x-python", 181 | "name": "python", 182 | "nbconvert_exporter": "python", 183 | "pygments_lexer": "ipython3", 184 | "version": "3.6.13" 185 | } 186 | }, 187 | "nbformat": 4, 188 | "nbformat_minor": 4 189 | } 190 | -------------------------------------------------------------------------------- /examples/markersize.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "markersize.ipynb", 7 | "provenance": [] 8 | }, 9 | "kernelspec": { 10 | "name": "python3", 11 | "display_name": "Python 3" 12 | }, 13 | "language_info": { 14 | "name": "python" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "code", 20 | "execution_count": 1, 21 | "metadata": { 22 | "id": "ZRx1oozi3WaS" 23 | }, 24 | "outputs": [], 25 | "source": [ 26 | "import matplotlib as mpl\n", 27 | "import matplotlib.pyplot as plt\n", 28 | "import numpy as np\n", 29 | "import pandas as pd\n", 30 | "import os,sys" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "source": [ 36 | "When plotting using `ax.scatter`, the `s` parameter is different from `markersize` parameter when using `ax.plot`, the former should be `markersize**2`, detailed explanation can be found at (https://stackoverflow.com/questions/14827650/pyplot-scatter-plot-marker-size#:~:text=So%20far%20the%20answer%20to,is%20hence%201%2F72%20inches.).\n", 37 | "\n", 38 | "But a more confusing thing is, the unit of the `s` or `markersize` is not the data unit shouwn in the axes or data, instead of, it represents the number of `points`. This notebook aims to illustrate what it is and how to specify `s` based on how many data units I want it to occupy (like, I want a dot occupy 2 data units)." 39 | ], 40 | "metadata": { 41 | "id": "nnJyM5oy4G4f" 42 | } 43 | }, 44 | { 45 | "cell_type": "code", 46 | "source": [ 47 | "def to_point_unit(s,fig,ax,xlim,ylim,scatter=True):\n", 48 | " # s means how many data units you want the marker to occupy\n", 49 | " ppi = 72 # matplotlib default point per inch is 72\n", 50 | " dpi = fig.dpi # matplotlib default dot/pixel per inch is 100\n", 51 | " ax.set_xlim(xlim)\n", 52 | " ax.set_ylim(ylim)\n", 53 | " fig.canvas.draw() # or using plt.pause(0.01)\n", 54 | " one_data_unit_to_one_display_unit = ax.get_window_extent().width/ (xlim[1]-xlim[0]) # display unit = pixel\n", 55 | " one_display_unit_to_one_point_unit = ppi / dpi\n", 56 | " one_data_unit_to_one_point_unit = one_data_unit_to_one_display_unit * one_display_unit_to_one_point_unit\n", 57 | " s_point_unit = one_data_unit_to_one_point_unit * s\n", 58 | " if scatter:\n", 59 | " s_point_unit = s_point_unit ** 2\n", 60 | " return s_point_unit" 61 | ], 62 | "metadata": { 63 | "id": "QtOLm9Ck5E1q" 64 | }, 65 | "execution_count": 2, 66 | "outputs": [] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "source": [ 71 | "fig, ax = plt.subplots()\n", 72 | "s = 1\n", 73 | "sp = to_point_unit(s,fig,ax,(0,10),(0,10),True)\n", 74 | "ax.scatter([4],[4],s=sp)" 75 | ], 76 | "metadata": { 77 | "colab": { 78 | "base_uri": "https://localhost:8080/", 79 | "height": 287 80 | }, 81 | "id": "LByB3AEQ5zLY", 82 | "outputId": "af297ff2-2571-4822-8f34-7284cfacd281" 83 | }, 84 | "execution_count": 3, 85 | "outputs": [ 86 | { 87 | "output_type": "execute_result", 88 | "data": { 89 | "text/plain": [ 90 | "" 91 | ] 92 | }, 93 | "metadata": {}, 94 | "execution_count": 3 95 | }, 96 | { 97 | "output_type": "display_data", 98 | "data": { 99 | "text/plain": [ 100 | "
" 101 | ], 102 | "image/png": "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\n" 103 | }, 104 | "metadata": { 105 | "needs_background": "light" 106 | } 107 | } 108 | ] 109 | } 110 | ] 111 | } -------------------------------------------------------------------------------- /examples/stacked_legends.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 18, 6 | "id": "94d19fcb-254d-42fa-ac2e-2ed38cf1b5c7", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "%matplotlib inline\n", 11 | "import numpy as np\n", 12 | "import pandas as pd\n", 13 | "import matplotlib.pyplot as plt\n", 14 | "import matplotlib as mpl\n", 15 | "import matplotlib.patches as mpatches" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 19, 21 | "id": "f7a50d61-a10e-4f4c-9a59-bbb2418964c3", 22 | "metadata": {}, 23 | "outputs": [ 24 | { 25 | "data": { 26 | "text/plain": [ 27 | "'module://ipykernel.pylab.backend_inline'" 28 | ] 29 | }, 30 | "execution_count": 19, 31 | "metadata": {}, 32 | "output_type": "execute_result" 33 | } 34 | ], 35 | "source": [ 36 | "mpl.get_backend()" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 20, 42 | "id": "892f8086-457e-4d41-b21c-24f969d64ca0", 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "mpl.use('MacOSX')" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 21, 52 | "id": "0d51fd25-2f23-4b87-acd6-e8d27c0dc96d", 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "def get_location_of_legend_box(leg_artist):\n", 57 | " frame = leg_artist.get_frame()\n", 58 | " x0 = frame.get_x()\n", 59 | " y0 = frame.get_y()\n", 60 | " x1 = x0 + frame.get_width()\n", 61 | " y1 = y0 + frame.get_height()\n", 62 | " ax_box_coord = ax.transAxes.inverted().transform([[x0, y0], [x1, y1]])\n", 63 | " width = ax_box_coord[1, 0] - ax_box_coord[0, 0]\n", 64 | " height = ax_box_coord[1, 1] - ax_box_coord[0, 1]\n", 65 | " lowest_point = ax_box_coord[0, 1]\n", 66 | " farthest_point = ax_box_coord[1, 0]\n", 67 | " return width,height,lowest_point,farthest_point\n", 68 | "\n", 69 | "def arrange_legend_boxs(legs_hl_list,ax):\n", 70 | " current_lowest_point = 1\n", 71 | " current_farthest_point = 1\n", 72 | " last_farthest_point = None\n", 73 | " have_legend_in_the_column = False\n", 74 | " ready_legend_artist = []\n", 75 | " for item in legs_hl_list:\n", 76 | " leg_artist = ax.legend(handles=item[0],labels=item[1],loc='upper left',bbox_to_anchor=(current_farthest_point,current_lowest_point))\n", 77 | " plt.pause(0.01)\n", 78 | " width,height,lowest_point,farthest_point = get_location_of_legend_box(leg_artist)\n", 79 | " if have_legend_in_the_column:\n", 80 | " if lowest_point < 0:\n", 81 | " current_farthest_point = max([last_farthest_point,farthest_point])\n", 82 | " leg_artist = ax.legend(handles=item[0],labels=item[1],loc='upper left',bbox_to_anchor=(current_farthest_point,1))\n", 83 | " plt.pause(0.01)\n", 84 | " width, height, lowest_point, farthest_point = get_location_of_legend_box(leg_artist)\n", 85 | " current_lowest_point = lowest_point\n", 86 | " last_farthest_point = farthest_point\n", 87 | " ready_legend_artist.append(leg_artist)\n", 88 | " have_legend_in_the_column = True\n", 89 | "\n", 90 | " for artist in ready_legend_artist:\n", 91 | " ax.add_artist(artist)" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": 22, 97 | "id": "a1d2f956-7f70-4883-b758-11cee07ed0c4", 98 | "metadata": {}, 99 | "outputs": [ 100 | { 101 | "data": { 102 | "image/png": "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+a5rJNi5c2d00aJFBcXFxYUFBQWFV1xxReHGjRvz0/mahFIAAAAAWePAgQOja2pqqlpaWvLuvPPOI4sXLz62e/fusbfddtuM559/frzv+oazAwcOWE1NzeiWlha74447EosXL3b/8R//oT/5kz/Jf/7559MWTAmlAAAAALJGQ0NDbOnSpZ83NDTse+655z7duHHj/vr6+r1m5h588MELjx49SoZJk4aGBi1dujTR0NDQ/pOf/OTUxo0bO+rr60+bmR588MH85uYBzV87aPxAAQAAAGSNWCwWrF69+lDPdQsWLGivra092traGq2rq2O0NE1isZhWr159que6BQsWBLW1ta61tVX//M//PCodr0soBQAAAJA1Zs+e3T5+/PhE7/U1NTWtkrRz586cuH9oLpo9e7bGjz8789fU1ASStHPnzrTkR0IpAAAAgKxRVlbWea71U6ZM6ZSkEydORDNb0cgxceJEd671F1xwgZOkEydO9Hlrz6EglAIAAADIGkeOHDnnhDqHDh3Kl6Rx48YFma1o5Pj888/PGTo/++wzk6Rx48adM7QOFaEUAAAAQNbYvXt34bFjx87KKdu3by+SpMsvv7w981WNDLt379axY8fOWr99+/aoJF1++eVnnVYdBkIpAAAAgKzR1tYWfeihh6b0XPfmm28Wbt68uTQWiwV33HHH2akJoWhra9NDDz00pue6N998M7p582aLxWL60z/90zPpeN28dHQKAAAAAOdjzpw5bevXr58Yj8fHzp07t62xsTF/y5Ytpc45e+qppz4uLS1Ny2gdpDlz5mj9+vWReDxe+O1vfzvR1NRkW7ZsMeecnnrqqc4JEyak5XUZKQUAAACQNaZNm3Z627Zte4uLi7vWrVtX9sorr4yfNWtW+4svvvjB8uXLGSVNo2nTprlt27adLi4udj//+c8jW7ZssUsuuUT/8i//0rl8+fJzTkAVBkZKAQAAAHg3c+bMM865ePe/X3/99Q991jOSVFVVJZxzX1yr+/rrr3dk8vUJpQAAAECWck7x/p+FdHBOTKiUIZy+CwAAAADwhlAKAAAAAPCGUAoAAAAA8IZQCgAAAADwhlAKAAAAAPCGUAoAAABgWHDO+S5hxEokEue9LaEUAAAA8KdTkguCgM/lIUgkEhFJTtKZgTxdkrq6utJa00jRI5QGg92Wgx8AAADw56NEItHR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\n", 103 | "text/plain": [ 104 | "
" 105 | ] 106 | }, 107 | "metadata": { 108 | "needs_background": "light" 109 | }, 110 | "output_type": "display_data" 111 | } 112 | ], 113 | "source": [ 114 | "## test\n", 115 | "leg1_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n", 116 | "leg2_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n", 117 | "leg3_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n", 118 | "leg4_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n", 119 | "leg5_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n", 120 | "leg6_hl = ([mpatches.Patch(color=i) for i in 'rgb'], ['r', 'g', 'b'])\n", 121 | "fig,ax = plt.subplots()\n", 122 | "arrange_legend_boxs([leg1_hl,leg2_hl,leg3_hl,leg4_hl,leg5_hl,leg6_hl],ax)" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": null, 128 | "id": "1c7822df-c047-47de-bf94-0eb8ebf7ffb7", 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": null, 136 | "id": "012ae3fb-11ef-44ab-82c0-853716c5174a", 137 | "metadata": {}, 138 | "outputs": [], 139 | "source": [] 140 | } 141 | ], 142 | "metadata": { 143 | "kernelspec": { 144 | "display_name": "Python 3", 145 | "language": "python", 146 | "name": "python3" 147 | }, 148 | "language_info": { 149 | "codemirror_mode": { 150 | "name": "ipython", 151 | "version": 3 152 | }, 153 | "file_extension": ".py", 154 | "mimetype": "text/x-python", 155 | "name": "python", 156 | "nbconvert_exporter": "python", 157 | "pygments_lexer": "ipython3", 158 | "version": "3.6.13" 159 | } 160 | }, 161 | "nbformat": 4, 162 | "nbformat_minor": 5 163 | } 164 | -------------------------------------------------------------------------------- /examples/yaxis_tick_on_right.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 4, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "import matplotlib\n", 11 | "import matplotlib.pyplot as plt\n", 12 | "import numpy as np" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 5, 18 | "metadata": {}, 19 | "outputs": [ 20 | { 21 | "data": { 22 | "image/png": "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\n", 23 | "text/plain": [ 24 | "
" 25 | ] 26 | }, 27 | "metadata": { 28 | "needs_background": "light" 29 | }, 30 | "output_type": "display_data" 31 | } 32 | ], 33 | "source": [ 34 | "fig,ax = plt.subplots()\n", 35 | "ax.set_yticks(np.arange(10))\n", 36 | "ax.set_yticklabels(np.arange(10))\n", 37 | "ax.yaxis.set_label_position('right')\n", 38 | "ax.yaxis.tick_right()" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 7, 44 | "metadata": {}, 45 | "outputs": [ 46 | { 47 | "data": { 48 | "image/png": "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\n", 49 | "text/plain": [ 50 | "
" 51 | ] 52 | }, 53 | "metadata": { 54 | "needs_background": "light" 55 | }, 56 | "output_type": "display_data" 57 | } 58 | ], 59 | "source": [ 60 | "fig,ax = plt.subplots()\n", 61 | "ax1 = ax.twinx()" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [] 70 | } 71 | ], 72 | "metadata": { 73 | "kernelspec": { 74 | "display_name": "Python 3", 75 | "language": "python", 76 | "name": "python3" 77 | }, 78 | "language_info": { 79 | "codemirror_mode": { 80 | "name": "ipython", 81 | "version": 3 82 | }, 83 | "file_extension": ".py", 84 | "mimetype": "text/x-python", 85 | "name": "python", 86 | "nbconvert_exporter": "python", 87 | "pygments_lexer": "ipython3", 88 | "version": "3.6.12" 89 | } 90 | }, 91 | "nbformat": 4, 92 | "nbformat_minor": 4 93 | } 94 | -------------------------------------------------------------------------------- /plotly/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | public_html 5 | 6 | 7 | 8 | 9 | 10 | 11 |
Hello world!
12 | 13 | -------------------------------------------------------------------------------- /plotly/network.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | 7 | -------------------------------------------------------------------------------- /plotly/plotly.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import pandas as pd 3 | 4 | # convert pandas edgelist or adjancencym matrix to network graph object 5 | df1 = pd.DataFrame({'source':['node1','node1','node2'],'target':['node2','node3','node3'],'weight':[4.5,4.5,4.5], 6 | 'color':['blue','green','blue']}). # edge list 7 | df2 = pd.DataFrame(data=[[0,4.5,4.5],[0,0,4.5],[0,0,0]],index=['node1','node2','node3'],columns=['node1','node2','node3']) # adjacency 8 | G1 = nx.from_pandas_edgelist(df1,source='source',target='target',edge_attr='weight',create_using=nx.Graph) 9 | G2 = nx.from_pandas_adjacency(df2,create_using=nx.Graph) 10 | 11 | # nodes anatomy 12 | type(G1.nodes()) 13 | # networkx.classes.reportviews.NodeView 14 | list(G1.nodes()) 15 | # ['node1', 'node2', 'node3'] 16 | type(G1.nodes(data=True)) 17 | # networkx.classes.reportviews.NodeDataView 18 | list(G1.nodes(data=True)) 19 | # [('node1', {}), ('node2', {}), ('node3', {})] 20 | G1.nodes['node1'] 21 | # {} 22 | 23 | 24 | # edges anatomy 25 | type(G1.edges()) 26 | # networkx.classes.reportviews.EdgeView 27 | list(G1.edges()) 28 | # [('node1', 'node2'), ('node1', 'node3'), ('node2', 'node3')] 29 | type(G1.edges(data=True)) 30 | # networkx.classes.reportviews.EdgeDataView 31 | list(G1.edges(data=True)) 32 | # [('node1', 'node2', {'weight': 4.5}), 33 | # ('node1', 'node3', {'weight': 4.5}), 34 | # ('node2', 'node3', {'weight': 4.5})] 35 | G1.edges[('node1','node2')] 36 | # {'weight': 4.5} 37 | 38 | 39 | # set and get attributes 40 | ## node 41 | node_color_dict = {'node1':'green','node2':'blue','node3':'red'} 42 | nx.set_node_attributes(G1,node_color_dict,'color') 43 | list(G1.nodes(data=True)) 44 | # [('node1', {'color': 'green'}), 45 | # ('node2', {'color': 'blue'}), 46 | # ('node3', {'color': 'red'})] 47 | ## edge 48 | nx.get_edge_attributes(G1,'weight') 49 | # {('node1', 'node2'): 4.5, ('node1', 'node3'): 4.5, ('node2', 'node3'): 4.5} 50 | 51 | 52 | import plotly.graph_objects as go 53 | ## step1: compute the graph layout (coordinates of nodes in 2D) 54 | coords_dict = nx.spring_layout(G1,seed=42) 55 | # {'node1': array([-0.33486468, 0.96136632]), 56 | # 'node2': array([ 1. , -0.19068184]), 57 | # 'node3': array([-0.66513532, -0.77068448])} 58 | ## step2: set the dictionary as the attribute of the node 59 | nx.set_node_attributes(G1,coords_dict,'coord') 60 | ## step3: validate 61 | G1.nodes['node1'] 62 | #{'color': 'green', 'coord': array([-0.33486468, 0.96136632])} 63 | 64 | 65 | node_x = [] # store x coordinates 66 | node_y = [] # store y coordinates 67 | node_text = [] # store text when mouse hovers over the node 68 | for node,node_attr_dict in G1.nodes(data=True): # recall anatomy 69 | x,y = node_attr_dict['coord'] 70 | node_x.append(x) 71 | node_y.append(y) 72 | node_text.append(node) 73 | node_trace = go.Scatter(name='nodes',x=node_x,y=node_y,mode='markers',hoverinfo='text',text=node_text,marker={'color':'green','size':5}) 74 | 75 | edge_x = [] 76 | edge_y = [] 77 | for edge_end1,edge_end2,edge_attr_dict in G1.edges(data=True): 78 | x0,y0 = G1.nodes[edge_end1]['coord'] 79 | x1,y1 = G1.nodes[edge_end2]['coord'] 80 | x2,y2 = None,None 81 | for x,y in zip([x0,x1,x2],[y0,y1,y2]): 82 | edge_x.append(x) 83 | edge_y.append(y) 84 | edge_trace = go.Scatter(name='lines',x=edge_x,y=edge_y,mode='lines',line=go.scatter.Line(color='black',width=2)) 85 | 86 | 87 | fig_layout = go.Layout(showlegend=True,title='network',xaxis=dict(title_text='coordinate x')) 88 | fig = go.Figure(data=[node_trace,edge_trace],layout=fig_layout) 89 | fig.write_html('./network.html',include_plotlyjs='cdn') 90 | 91 | 92 | -------------------------------------------------------------------------------- /rcParams.txt: -------------------------------------------------------------------------------- 1 | _internal.classic_mode 2 | agg.path.chunksize 3 | animation.avconv_args 4 | animation.avconv_path 5 | animation.bitrate 6 | animation.codec 7 | animation.convert_args 8 | animation.convert_path 9 | animation.embed_limit 10 | animation.ffmpeg_args 11 | animation.ffmpeg_path 12 | animation.frame_format 13 | animation.html 14 | animation.html_args 15 | animation.writer 16 | axes.autolimit_mode 17 | axes.axisbelow 18 | axes.edgecolor 19 | axes.facecolor 20 | axes.formatter.limits 21 | axes.formatter.min_exponent 22 | axes.formatter.offset_threshold 23 | axes.formatter.use_locale 24 | axes.formatter.use_mathtext 25 | axes.formatter.useoffset 26 | axes.grid 27 | axes.grid.axis 28 | axes.grid.which 29 | axes.labelcolor 30 | axes.labelpad 31 | axes.labelsize 32 | axes.labelweight 33 | axes.linewidth 34 | axes.prop_cycle 35 | axes.spines.bottom 36 | axes.spines.left 37 | axes.spines.right 38 | axes.spines.top 39 | axes.titlecolor 40 | axes.titlelocation 41 | axes.titlepad 42 | axes.titlesize 43 | axes.titleweight 44 | axes.titley 45 | axes.unicode_minus 46 | axes.xmargin 47 | axes.ymargin 48 | axes3d.grid 49 | backend 50 | backend_fallback 51 | boxplot.bootstrap 52 | boxplot.boxprops.color 53 | boxplot.boxprops.linestyle 54 | boxplot.boxprops.linewidth 55 | boxplot.capprops.color 56 | boxplot.capprops.linestyle 57 | boxplot.capprops.linewidth 58 | boxplot.flierprops.color 59 | boxplot.flierprops.linestyle 60 | boxplot.flierprops.linewidth 61 | boxplot.flierprops.marker 62 | boxplot.flierprops.markeredgecolor 63 | boxplot.flierprops.markeredgewidth 64 | boxplot.flierprops.markerfacecolor 65 | boxplot.flierprops.markersize 66 | boxplot.meanline 67 | boxplot.meanprops.color 68 | boxplot.meanprops.linestyle 69 | boxplot.meanprops.linewidth 70 | boxplot.meanprops.marker 71 | boxplot.meanprops.markeredgecolor 72 | boxplot.meanprops.markerfacecolor 73 | boxplot.meanprops.markersize 74 | boxplot.medianprops.color 75 | boxplot.medianprops.linestyle 76 | boxplot.medianprops.linewidth 77 | boxplot.notch 78 | boxplot.patchartist 79 | boxplot.showbox 80 | boxplot.showcaps 81 | boxplot.showfliers 82 | boxplot.showmeans 83 | boxplot.vertical 84 | boxplot.whiskerprops.color 85 | boxplot.whiskerprops.linestyle 86 | boxplot.whiskerprops.linewidth 87 | boxplot.whiskers 88 | contour.corner_mask 89 | contour.linewidth 90 | contour.negative_linestyle 91 | date.autoformatter.day 92 | date.autoformatter.hour 93 | date.autoformatter.microsecond 94 | date.autoformatter.minute 95 | date.autoformatter.month 96 | date.autoformatter.second 97 | date.autoformatter.year 98 | date.epoch 99 | docstring.hardcopy 100 | errorbar.capsize 101 | figure.autolayout 102 | figure.constrained_layout.h_pad 103 | figure.constrained_layout.hspace 104 | figure.constrained_layout.use 105 | figure.constrained_layout.w_pad 106 | figure.constrained_layout.wspace 107 | figure.dpi 108 | figure.edgecolor 109 | figure.facecolor 110 | figure.figsize 111 | figure.frameon 112 | figure.max_open_warning 113 | figure.raise_window 114 | figure.subplot.bottom 115 | figure.subplot.hspace 116 | figure.subplot.left 117 | figure.subplot.right 118 | figure.subplot.top 119 | figure.subplot.wspace 120 | figure.titlesize 121 | figure.titleweight 122 | font.cursive 123 | font.family 124 | font.fantasy 125 | font.monospace 126 | font.sans-serif 127 | font.serif 128 | font.size 129 | font.stretch 130 | font.style 131 | font.variant 132 | font.weight 133 | grid.alpha 134 | grid.color 135 | grid.linestyle 136 | grid.linewidth 137 | hatch.color 138 | hatch.linewidth 139 | hist.bins 140 | image.aspect 141 | image.cmap 142 | image.composite_image 143 | image.interpolation 144 | image.lut 145 | image.origin 146 | image.resample 147 | interactive 148 | keymap.all_axes 149 | keymap.back 150 | keymap.copy 151 | keymap.forward 152 | keymap.fullscreen 153 | keymap.grid 154 | keymap.grid_minor 155 | keymap.help 156 | keymap.home 157 | keymap.pan 158 | keymap.quit 159 | keymap.quit_all 160 | keymap.save 161 | keymap.xscale 162 | keymap.yscale 163 | keymap.zoom 164 | legend.borderaxespad 165 | legend.borderpad 166 | legend.columnspacing 167 | legend.edgecolor 168 | legend.facecolor 169 | legend.fancybox 170 | legend.fontsize 171 | legend.framealpha 172 | legend.frameon 173 | legend.handleheight 174 | legend.handlelength 175 | legend.handletextpad 176 | legend.labelspacing 177 | legend.loc 178 | legend.markerscale 179 | legend.numpoints 180 | legend.scatterpoints 181 | legend.shadow 182 | legend.title_fontsize 183 | lines.antialiased 184 | lines.color 185 | lines.dash_capstyle 186 | lines.dash_joinstyle 187 | lines.dashdot_pattern 188 | lines.dashed_pattern 189 | lines.dotted_pattern 190 | lines.linestyle 191 | lines.linewidth 192 | lines.marker 193 | lines.markeredgecolor 194 | lines.markeredgewidth 195 | lines.markerfacecolor 196 | lines.markersize 197 | lines.scale_dashes 198 | lines.solid_capstyle 199 | lines.solid_joinstyle 200 | markers.fillstyle 201 | mathtext.bf 202 | mathtext.cal 203 | mathtext.default 204 | mathtext.fallback 205 | mathtext.fallback_to_cm 206 | mathtext.fontset 207 | mathtext.it 208 | mathtext.rm 209 | mathtext.sf 210 | mathtext.tt 211 | mpl_toolkits.legacy_colorbar 212 | patch.antialiased 213 | patch.edgecolor 214 | patch.facecolor 215 | patch.force_edgecolor 216 | patch.linewidth 217 | path.effects 218 | path.simplify 219 | path.simplify_threshold 220 | path.sketch 221 | path.snap 222 | pcolor.shading 223 | pdf.compression 224 | pdf.fonttype 225 | pdf.inheritcolor 226 | pdf.use14corefonts 227 | pgf.preamble 228 | pgf.rcfonts 229 | pgf.texsystem 230 | polaraxes.grid 231 | ps.distiller.res 232 | ps.fonttype 233 | ps.papersize 234 | ps.useafm 235 | ps.usedistiller 236 | savefig.bbox 237 | savefig.directory 238 | savefig.dpi 239 | savefig.edgecolor 240 | savefig.facecolor 241 | savefig.format 242 | savefig.jpeg_quality 243 | savefig.orientation 244 | savefig.pad_inches 245 | savefig.transparent 246 | scatter.edgecolors 247 | scatter.marker 248 | svg.fonttype 249 | svg.hashsalt 250 | svg.image_inline 251 | text.antialiased 252 | text.color 253 | text.hinting 254 | text.hinting_factor 255 | text.kerning_factor 256 | text.latex.preamble 257 | text.latex.preview 258 | text.usetex 259 | timezone 260 | tk.window_focus 261 | toolbar 262 | webagg.address 263 | webagg.open_in_browser 264 | webagg.port 265 | webagg.port_retries 266 | xaxis.labellocation 267 | xtick.alignment 268 | xtick.bottom 269 | xtick.color 270 | xtick.direction 271 | xtick.labelbottom 272 | xtick.labelsize 273 | xtick.labeltop 274 | xtick.major.bottom 275 | xtick.major.pad 276 | xtick.major.size 277 | xtick.major.top 278 | xtick.major.width 279 | xtick.minor.bottom 280 | xtick.minor.pad 281 | xtick.minor.size 282 | xtick.minor.top 283 | xtick.minor.visible 284 | xtick.minor.width 285 | xtick.top 286 | yaxis.labellocation 287 | ytick.alignment 288 | ytick.color 289 | ytick.direction 290 | ytick.labelleft 291 | ytick.labelright 292 | ytick.labelsize 293 | ytick.left 294 | ytick.major.left 295 | ytick.major.pad 296 | ytick.major.right 297 | ytick.major.size 298 | ytick.major.width 299 | ytick.minor.left 300 | ytick.minor.pad 301 | ytick.minor.right 302 | ytick.minor.size 303 | ytick.minor.visible 304 | ytick.minor.width 305 | ytick.right 306 | -------------------------------------------------------------------------------- /sankey/Sankey_tutorial.py: -------------------------------------------------------------------------------- 1 | 2 | import pandas as pd 3 | import matplotlib.pyplot as plt 4 | import numpy as np 5 | from matplotlib.path import Path 6 | from matplotlib.patches import PathPatch, Rectangle 7 | 8 | # draw the canvas and ax 9 | fig,ax = plt.subplots() 10 | ax.set_xlim([0,1]) 11 | ax.set_ylim([0,1]) 12 | ax.grid() 13 | 14 | # draw the recs 15 | rec_left = Rectangle(xy=(0.1,0.6),width=0.2,height=0.2,facecolor='orange',edgecolor='k') 16 | ax.add_patch(rec_left) 17 | rec_right = Rectangle(xy=(0.7,0.2),width=0.2,height=0.2,facecolor='green',edgecolor='k') 18 | ax.add_patch(rec_right) 19 | 20 | # demo the path object logics 21 | verts = [(0.3,0.8),(0.5,0.8),(0.7,0.4),(0.3,0.6),(0.3,0.8)] 22 | codes = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY] 23 | p = Path(verts,codes) 24 | ax.add_patch(PathPatch(p,fc='none')) 25 | 26 | # method1, Path, demo the curve4 logics 27 | verts = [(0.3,0.8), (0.5,0.8), (0.5,0.4), (0.7,0.4)] 28 | codes = [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4] 29 | p = Path(verts,codes) 30 | ax.add_patch(PathPatch(p,fc='none',alpha=0.6)) 31 | 32 | # method1, path 33 | verts = [(0.3,0.8), (0.5,0.8), (0.5,0.4), (0.7,0.4), (0.7,0.2), (0.5,0.2), (0.5,0.6), (0.3,0.6), (0.3,0.8)] 34 | codes = [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4, Path.LINETO, Path.CURVE4, Path.CURVE4, Path.CURVE4, Path.CLOSEPOLY] 35 | p = Path(verts,codes) 36 | ax.add_patch(PathPatch(p,fc='red',alpha=0.6)) 37 | 38 | # method2, convolve 39 | yu = np.array(50*[0.8] + 50*[0.4]) 40 | yu_c = np.convolve(yu, 0.05*np.ones(20),mode='valid') 41 | yu_cc = np.convolve(yu_c, 0.05*np.ones(20),mode='valid') 42 | yd = np.array(50*[0.6] + 50*[0.2]) 43 | yd_c = np.convolve(yd, 0.05*np.ones(20),mode='valid') 44 | yd_cc = np.convolve(yd_c, 0.05*np.ones(20),mode='valid') 45 | ax.fill_between(np.linspace(0.3,0.7,62),yd_cc,yu_cc,color='blue',alpha=0.6) -------------------------------------------------------------------------------- /sankey/sankey_tutorial.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frankligy/python_visualization_tutorial/1ac56c55a7e7f317296cffc98dc43014df57a77f/sankey/sankey_tutorial.pptx -------------------------------------------------------------------------------- /sankey/sankey_tutorial_bezier.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frankligy/python_visualization_tutorial/1ac56c55a7e7f317296cffc98dc43014df57a77f/sankey/sankey_tutorial_bezier.ai -------------------------------------------------------------------------------- /tutorial3_boxplot_etc.py: -------------------------------------------------------------------------------- 1 | import matplotlib as mpl 2 | import matplotlib.pyplot as plt 3 | from matplotlib.colors import ListedColormap 4 | 5 | mpl.rcParams['pdf.fonttype'] = 42 6 | mpl.rcParams['ps.fonttype'] = 42 7 | mpl.rcParams['font.family'] = 'Arial' 8 | 9 | import numpy as np 10 | 11 | np.random.seed(42) 12 | data1 = np.random.randn(100) 13 | data2 = np.random.randn(100) 14 | data3 = np.random.randn(100) 15 | 16 | fig,ax = plt.subplots() 17 | bp = ax.boxplot(x=[data1,data2,data3],positions=[1,5,7],patch_artist=True) 18 | for flier in bp['fliers']: 19 | flier.set_markersize(9) 20 | flier.set_marker('v') 21 | for box in bp['boxes']: 22 | box.set_facecolor('green') 23 | box.set_edgecolor('black') 24 | box.set_linewidth(2) 25 | for whisker in bp['whiskers']: 26 | whisker.set_linewidth(5) 27 | for cap in bp['caps']: 28 | cap.set_color('red') 29 | cap.set_linewidth(10) 30 | for median in bp['medians']: 31 | median.set_linewidth(15) 32 | 33 | 34 | fig,ax = plt.subplots() 35 | ax.bar(x=[1,4,9],height=(data1.max(),data2.max(),data3.max()),width=0.5,edgecolor='black',color=['green','red','orange'], 36 | yerr=np.array([[0.1,0.1,0.1],[0.15,0.15,0.15]]),ecolor='red',capsize=5) 37 | 38 | 39 | fig,ax = plt.subplots() 40 | ax.hist(x=[data1,data2],bins=20,edgecolor='black') 41 | 42 | fig,ax = plt.subplots() 43 | ax.scatter(x=np.arange(10),y=np.arange(10)+5,s=np.arange(10)*10,c=np.random.rand(10),cmap='spring') 44 | ax.scatter(x=[1,2,3],y=[1,2,3],s=[100,200,300],c=['r','g','b']) 45 | 46 | 47 | 48 | fig,ax = plt.subplots() 49 | ax.imshow(np.random.randn(5,5),cmap='Set1') 50 | ax.set_xticks(np.linspace(0.5,3.5,4)) 51 | ax.set_yticks(np.linspace(0.5,3.5,4)) 52 | ax.tick_params(axis='both',length=0,labelsize=0) 53 | ax.grid(b=True,which='major',axis='both',color='black') 54 | ax.text(-0.2,3,'hey') 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /tutorial5_seaborn.py: -------------------------------------------------------------------------------- 1 | import matplotlib as mpl 2 | import matplotlib.pyplot as plt 3 | from matplotlib.colors import ListedColormap 4 | 5 | mpl.rcParams['pdf.fonttype'] = 42 6 | mpl.rcParams['ps.fonttype'] = 42 7 | mpl.rcParams['font.family'] = 'Arial' 8 | 9 | import numpy as np 10 | 11 | np.random.seed(42) 12 | data1 = np.random.randn(100) 13 | data2 = np.random.randn(100) 14 | data3 = np.random.randn(100) 15 | 16 | import seaborn as sns 17 | import pandas as pd 18 | 19 | # prepare datasets 20 | 21 | penguin = sns.load_dataset('penguins') # long form 22 | synthesis = pd.DataFrame({'var1':data1,'var2':data2,'var3':data3}) # wideform 23 | a = synthesis.stack().reset_index(-1) 24 | 25 | # distribution plot 26 | 27 | fig,ax = plt.subplots() 28 | sns.histplot(data=penguin,kde=True,stat='frequency',x='bill_length_mm',hue='species',multiple='layer', 29 | kde_kws={'bw_adjust':5},line_kws={'linewidth':7},palette='Set2',ax=ax) 30 | sns.rugplot(data=penguin,x='bill_length_mm',hue='species',ax=ax) 31 | sns.histplot(data=synthesis,kde=True,stat='density',common_norm=False,hue_order=['var2','var1','var3'], 32 | multiple='layer') 33 | 34 | 35 | sns.kdeplot(data=penguin,x='bill_length_mm',hue='species',clip=(35,100)) 36 | sns.rugplot(data=penguin,x='bill_length_mm',hue='species') 37 | 38 | 39 | 40 | # categorical plot 41 | sns.violinplot(data=penguin,x='species',y='bill_length_mm',hue='sex',split=True,bw=0.2,inner='quartile',scale_hue=True, 42 | scale='count') 43 | 44 | 45 | 46 | sns.swarmplot(data=penguin,x='species',y='bill_length_mm',hue='sex',dodge=True) 47 | 48 | sns.pointplot(data=penguin,x='species',y='bill_length_mm',hue='sex') 49 | 50 | # regression plot 51 | sns.regplot(data=penguin,x='bill_length_mm',y='bill_depth_mm') 52 | 53 | # matrix plot 54 | sns.heatmap(data=synthesis.iloc[0:5,:],annot=True,linewidths=0.5,square=True,yticklabels=False) 55 | mask = np.array([[0,0,0], 56 | [0,0,0], 57 | [0,1,0], 58 | [0,0,0], 59 | [0,0,0]]) 60 | sns.heatmap(data=synthesis.iloc[0:5,:],annot=True,linewidths=0.5,square=True,yticklabels=False,mask=mask) 61 | 62 | 63 | row_cb = pd.DataFrame(data=np.random.choice(['r','g','b','m'],(100,2)),index=np.arange(100),columns=['hey','ha']) 64 | sns.clustermap(data=synthesis,row_colors=row_cb) 65 | 66 | 67 | # pair plot and joint plot 68 | sns.pairplot(data=penguin.iloc[:,[2,3,4,5]],dropna=True) 69 | sns.jointplot(data=penguin,x='bill_length_mm',y='bill_depth_mm',kind='reg') 70 | 71 | 72 | -------------------------------------------------------------------------------- /tutorial_4_violin_dendrogram.py: -------------------------------------------------------------------------------- 1 | import matplotlib as mpl 2 | import matplotlib.pyplot as plt 3 | from matplotlib.colors import ListedColormap 4 | 5 | mpl.rcParams['pdf.fonttype'] = 42 6 | mpl.rcParams['ps.fonttype'] = 42 7 | mpl.rcParams['font.family'] = 'Arial' 8 | 9 | import numpy as np 10 | 11 | np.random.seed(42) 12 | data1 = np.random.randn(100) 13 | data2 = np.random.randn(100) 14 | data3 = np.random.randn(100) 15 | 16 | dataset = [data1,data2,data3] 17 | positions = [1,5,7] 18 | fig,ax = plt.subplots() 19 | vp = ax.violinplot(dataset=dataset,positions=[1,5,7]) 20 | 21 | for body in vp['bodies']: 22 | body.set_facecolor('red') 23 | body.set_edgecolor('black') 24 | body.set_alpha(1) 25 | vp['cmaxes'].set_color('black') 26 | vp['cmins'].set_color('black') 27 | vp['cbars'].set_color('black') 28 | 29 | tmp = [np.percentile(data,[25,50,75]) for data in dataset] 30 | 31 | def get_whisker(tmp,dataset): 32 | whisker = [] 33 | for quantile,data in zip(tmp,dataset): 34 | data = np.array(data) 35 | q1 = quantile[0] 36 | median = quantile[1] 37 | q3 = quantile[2] 38 | iqr = q3 - q1 39 | upper = q3 + 1.5 * iqr 40 | upper = np.clip(upper,q3,data.max()) 41 | lower = q1 - 1.5 * iqr 42 | lower = np.clip(lower,data.min(),q1) 43 | whisker.append((upper,lower)) 44 | return whisker 45 | 46 | whisker = get_whisker(tmp,dataset) 47 | ax.scatter(positions,[quantile[1] for quantile in tmp],marker='o',color='white',s=30,zorder=3) 48 | ax.vlines(positions,[quantile[0] for quantile in tmp],[quantile[2] for quantile in tmp],color='black',linestyle='-',lw=5) 49 | ax.vlines(positions,[bound[0] for bound in whisker],[bound[1] for bound in whisker],color='black',linestyle='-',lw=4) 50 | 51 | 52 | sample1 = np.random.randn(100) 53 | sample2 = np.random.randn(100) 54 | sample3 = np.random.randn(100) 55 | sample4 = np.random.randn(100) 56 | sample5 = np.random.randn(100) 57 | sample6 = np.random.randn(100) 58 | 59 | mat = np.row_stack([sample1,sample2,sample3,sample4,sample5,sample6]) 60 | 61 | from scipy.spatial.distance import pdist,squareform 62 | dense_distance = pdist(mat,'euclidean') 63 | square_distance = squareform(dense_distance) 64 | 65 | from scipy.cluster.hierarchy import linkage,dendrogram 66 | linkage_matrix = linkage(dense_distance,method='ward',metric='euclidean') 67 | fig,ax = plt.subplots() 68 | dendrogram(linkage_matrix,ax=ax) 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | --------------------------------------------------------------------------------