-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy path08_Matplotlib.html
More file actions
2055 lines (2002 loc) · 251 KB
/
08_Matplotlib.html
File metadata and controls
2055 lines (2002 loc) · 251 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8">
<meta name="generator" content="quarto-1.3.450">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<meta name="author" content="Andrés Quintero-Zea">
<meta name="dcterms.date" content="2024-09-09">
<title>Visualización de datos con Matplotlib y Seaborn</title>
<style>
code {
white-space: pre-wrap;
}
span.smallcaps {
font-variant: small-caps;
}
div.columns {
display: flex;
gap: min(4vw, 1.5em);
}
div.column {
flex: auto;
overflow-x: auto;
}
div.hanging-indent {
margin-left: 1.5em;
text-indent: -1.5em;
}
ul.task-list {
list-style: none;
}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1em;
/* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */
vertical-align: middle;
}
/* CSS for syntax highlighting */
pre>code.sourceCode {
white-space: pre;
position: relative;
}
pre>code.sourceCode>span {
display: inline-block;
line-height: 1.25;
}
pre>code.sourceCode>span:empty {
height: 1.2em;
}
.sourceCode {
overflow: visible;
}
code.sourceCode>span {
color: inherit;
text-decoration: inherit;
}
div.sourceCode {
margin: 1em 0;
}
pre.sourceCode {
margin: 0;
}
@media screen {
div.sourceCode {
overflow: auto;
}
}
@media print {
pre>code.sourceCode {
white-space: pre-wrap;
}
pre>code.sourceCode>span {
text-indent: -5em;
padding-left: 5em;
}
}
pre.numberSource code {
counter-reset: source-line 0;
}
pre.numberSource code>span {
position: relative;
left: -4em;
counter-increment: source-line;
}
pre.numberSource code>span>a:first-child::before {
content: counter(source-line);
position: relative;
left: -1em;
text-align: right;
vertical-align: baseline;
border: none;
display: inline-block;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
padding: 0 4px;
width: 4em;
}
pre.numberSource {
margin-left: 3em;
padding-left: 4px;
}
@media screen {
pre>code.sourceCode>span>a:first-child::before {
text-decoration: underline;
}
}
</style>
<script src="assets/quarto-nav/quarto-nav.js"></script>
<script src="assets/quarto-nav/headroom.min.js"></script>
<script src="assets/clipboard/clipboard.min.js"></script>
<script src="assets/quarto-search/autocomplete.umd.js"></script>
<script src="assets/quarto-search/fuse.min.js"></script>
<script src="assets/quarto-search/quarto-search.js"></script>
<meta name="quarto:offset" content="./">
<link href="./09_EDA.html" rel="next">
<link href="./07_Pandas.html" rel="prev">
<script src="assets/quarto-html/quarto.js"></script>
<script src="assets/quarto-html/popper.min.js"></script>
<script src="assets/quarto-html/tippy.umd.min.js"></script>
<script src="assets/quarto-html/anchor.min.js"></script>
<link href="assets/quarto-html/tippy.css" rel="stylesheet">
<link href="assets/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet"
id="quarto-text-highlighting-styles">
<script src="assets/bootstrap/bootstrap.min.js"></script>
<link href="assets/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="assets/bootstrap/bootstrap.min.css" rel="stylesheet" id="quarto-bootstrap" data-mode="light">
<script id="quarto-search-options" type="application/json">{
"location": "sidebar",
"copy-button": false,
"collapse-after": 3,
"panel-placement": "start",
"type": "textbox",
"limit": 20,
"language": {
"search-no-results-text": "No results",
"search-matching-documents-text": "matching documents",
"search-copy-link-title": "Copy link to search",
"search-hide-matches-text": "Hide additional matches",
"search-more-match-text": "more match in this document",
"search-more-matches-text": "more matches in this document",
"search-clear-button-title": "Clear",
"search-detached-cancel-button-title": "Cancel",
"search-submit-button-title": "Submit",
"search-label": "Search"
}
}</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"
integrity="sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg=="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg=="
crossorigin="anonymous"></script>
<script type="application/javascript">define('jquery', [], function () { return window.jQuery; })</script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=default'></script>
</head>
<body class="nav-sidebar floating">
<!-- content -->
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article">
<!-- sidebar -->
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal sidebar-navigation floating overflow-auto">
<div class="pt-lg-2 mt-2 text-left sidebar-header sidebar-header-stacked">
<img src="./LogoNuevo.png" alt="" class="sidebar-logo py-0 d-lg-inline d-none">
<div class="sidebar-title mb-0 py-0">
<a href="./index.html">Programación PRE2013A45</a>
</div>
</div>
<div class="sidebar-menu-container">
<ul class="list-unstyled mt-1">
<li class="sidebar-item sidebar-item-section">
<div class="sidebar-item-container">
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse"
data-bs-target="#quarto-sidebar-section-1" aria-expanded="true">
<span class="menu-text">Python</span></a>
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse"
data-bs-target="#quarto-sidebar-section-1" aria-expanded="true"
aria-label="Toggle section">
<i class="bi bi-chevron-right ms-2"></i>
</a>
</div>
<ul id="quarto-sidebar-section-1" class="collapse list-unstyled sidebar-section depth1 show">
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./01_Intro_Python.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">1</span> <span
class="chapter-title">Introducción a Python</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./02_Estructuras_control.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">2</span> <span
class="chapter-title">Estructuras de control</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./03_Funciones.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">3</span> <span
class="chapter-title">Funciones</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./04_Estructura_datos.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">4</span> <span
class="chapter-title">Estructuras de datos avanzadas</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./05_Archivos_excepciones.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">5</span> <span
class="chapter-title">Manejo de archivos y excepciones</span></span></a>
</div>
</li>
</ul>
</li>
<li class="sidebar-item sidebar-item-section">
<div class="sidebar-item-container">
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse"
data-bs-target="#quarto-sidebar-section-2" aria-expanded="true">
<span class="menu-text">Análisis de Datos</span></a>
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse"
data-bs-target="#quarto-sidebar-section-2" aria-expanded="true"
aria-label="Toggle section">
<i class="bi bi-chevron-right ms-2"></i>
</a>
</div>
<ul id="quarto-sidebar-section-2" class="collapse list-unstyled sidebar-section depth1 show">
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./06_Numpy.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">6</span> <span
class="chapter-title">Introducción a Numpy</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./07_Pandas.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">7</span> <span
class="chapter-title">Manipulación de datos con Pandas</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./08_Matplotlib.html" class="sidebar-item-text sidebar-link active">
<span class="menu-text"><span class="chapter-number">8</span> <span
class="chapter-title">Visualización de datos con
Matplotlib y Seaborn</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./09_EDA.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">9</span> <span
class="chapter-title">Análisis exploratorio de datos</span></span></a>
</div>
</li>
</ul>
</li>
<li class="sidebar-item sidebar-item-section">
<div class="sidebar-item-container">
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse"
data-bs-target="#quarto-sidebar-section-3" aria-expanded="true">
<span class="menu-text">Ciencia de Datos</span></a>
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse"
data-bs-target="#quarto-sidebar-section-3" aria-expanded="true"
aria-label="Toggle section">
<i class="bi bi-chevron-right ms-2"></i>
</a>
</div>
<ul id="quarto-sidebar-section-3" class="collapse list-unstyled sidebar-section depth1 show">
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./10_Intro_DS.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">10</span> <span
class="chapter-title">Introducción a la ciencia de
datos</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./11_Clasificacion.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">11</span> <span
class="chapter-title">Modelos de clasificación</span></span></a>
</div>
</li>
<li class="sidebar-item">
<div class="sidebar-item-container">
<a href="./12_Regresion.html" class="sidebar-item-text sidebar-link">
<span class="menu-text"><span class="chapter-number">12</span> <span
class="chapter-title">Modelos de regresión</span></span></a>
</div>
</li>
</ul>
</li>
</ul>
</div>
</nav>
<div id="quarto-sidebar-glass" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar,#quarto-sidebar-glass">
</div>
<!-- margin-sidebar -->
<div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
<nav id="TOC" role="doc-toc" class="toc-active">
<h2 id="toc-title">Tabla de contenidos</h2>
<ul>
<li><a href="#objetivo" id="toc-objetivo" class="nav-link active"
data-scroll-target="#objetivo">Objetivo</a></li>
<li><a href="#consejos-generales-sobre-matplotlib" id="toc-consejos-generales-sobre-matplotlib" class="nav-link"
data-scroll-target="#consejos-generales-sobre-matplotlib"><span class="header-section-number"> 8.1 </span> Consejos generales sobre Matplotlib </a></li>
<li><a href="#dos-interfaces-por-el-precio-de-una" id="toc-dos-interfaces-por-el-precio-de-una" class="nav-link"
data-scroll-target="#dos-interfaces-por-el-precio-de-una"><span class="header-section-number"> 8.2 </span> Dos interfaces por el precio de una </a>
</li>
<li><a href="#gráficos-de-líneas-simples" id="toc-gráficos-de-líneas-simples" class="nav-link"
data-scroll-target="#gráficos-de-líneas-simples"><span class="header-section-number"> 8.3 </span> Gráficos de líneas simples </a>
</li>
<li><a href="#diagramas-de-dispersión-simples" id="toc-diagramas-de-dispersión-simples" class="nav-link"
data-scroll-target="#diagramas-de-dispersión-simples"><span class="header-section-number"> 8.4 </span> Diagramas de dispersión simples </a>
</li>
<li><a href="#visualizando-errores" id="toc-visualizando-errores" class="nav-link"
data-scroll-target="#visualizando-errores"><span class="header-section-number"> 8.5 </span> Visualizando errores</a>
</li>
<li><a href="#gráficas-de-densidad-y-contorno" id="toc-gráficas-de-densidad-y-contorno" class="nav-link"
data-scroll-target="#gráficas-de-densidad-y-contorno"><span class="header-section-number"> 8.6 </span> Gráficas de densidad y contorno </a>
</li>
<li><a href="#histogramas-binnings-y-densidad" id="toc-histogramas-binnings-y-densidad" class="nav-link"
data-scroll-target="#histogramas-binnings-y-densidad"><span class="header-section-number"> 8.7 </span> Histogramas, binnings y densidad </a>
</li>
<li><a href="#personalización-de-leyendas" id="toc-personalización-de-leyendas" class="nav-link"
data-scroll-target="#personalización-de-leyendas"><span class="header-section-number"> 8.8 </span> Personalización de leyendas </a>
</li>
<li><a href="#varias-subgráficas" id="toc-varias-subgráficas" class="nav-link"
data-scroll-target="#varias-subgráficas"><span class="header-section-number"> 8.9 </span> Varias subgráficas </a>
</li>
<li><a href="#texto-y-anotaciones" id="toc-texto-y-anotaciones" class="nav-link"
data-scroll-target="#texto-y-anotaciones"><span class="header-section-number"> 8.10 </span> Texto y anotaciones </a>
</li>
<li><a href="#personalización-de-ticks" id="toc-personalización-de-ticks" class="nav-link"
data-scroll-target="#personalización-de-ticks"><span class="header-section-number"> 8.11 </span> Personalización de ticks </a>
</li>
<li><a href="#personalización-de-matplotlib" id="toc-personalización-de-matplotlib" class="nav-link"
data-scroll-target="#personalización-de-matplotlib"><span class="header-section-number"> 8.12 </span> Personalización de Matplotlib </a>
</li>
<li><a href="#visualización-con-seaborn" id="toc-visualización-con-seaborn" class="nav-link"
data-scroll-target="#visualización-con-seaborn"><span class="header-section-number"> 8.13 </span> Visualización con Seaborn </a>
</li>
<li><a href="#practice-exercises" id="toc-practice-exercises" class="nav-link"
data-scroll-target="#practice-exercises"><span class="header-section-number">8.14</span>
Ejercicios prácticos</a></li>
</ul>
</nav>
</div>
<!-- main -->
<main class="content" id="quarto-document-content">
<header id="title-block-header" class="quarto-title-block default">
<div class="quarto-title">
<h1 class="title"><span class="chapter-number">8</span> <span
class="chapter-title">Visualización de datos con Matplotlib y Seaborn</span></h1>
</div>
<div class="quarto-title-meta"> </div>
</header>
<section id="objetivo" class="level1">
<h1 class="anchored" data-anchor-id="objetivo">Objetivo</h1>
<p>
El objetivo de esta clase es enseñar a los estudiantes a crear visualizaciones de datos utilizando matplotlib y seaborn en Python, permitiéndoles representar gráficamente la información para explorar y analizar patrones y relaciones en los datos de manera efectiva.</p>
</section>
<section id="consejos-generales-sobre-matplotlib" class="level2">
<h2 class="anchored" data-anchor-id="consejos-generales-sobre-matplotlib">8.1 Consejos generales sobre Matplotlib</h2>
<p>Antes de profundizar en los detalles de la creación de visualizaciones con Matplotlib, hay algunas cosas útiles que debe saber sobre el uso del paquete.</p>
<section id="importación-de-matplotlib" class="level3">
<h3 class="anchored" data-anchor-id="importación-de-matplotlib">8.1.1 Importación de Matplotlib</h3>
<p>Así como usamos la abreviatura <code>np</code> para NumPy y la abreviatura <code>pd</code> para Pandas, usaremos algunas abreviaturas de uso común para las importaciones de Matplotlib:</p>
<div id="41e4e2b3" class="cell">
<div class="sourceCode cell-code" id="cb1"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> matplotlib <span class="im">as</span> mpl</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> matplotlib.pyplot <span class="im">as</span> plt</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> matplotlib_inline.backend_inline <span class="im">import</span> set_matplotlib_formats</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>set_matplotlib_formats(<span class="st">'pdf'</span>, <span class="st">'svg'</span>)</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>matplotlib inline</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>La interfaz <code>plt</code> es la que utilizaremos con más frecuencia, como veremos a lo largo de este capítulo.</p>
</section>
<section id="estilos-de-configuración" class="level3">
<h3 class="anchored" data-anchor-id="estilos-de-configuración">8.1.2 Estilos de configuración</h3>
<p>Utilizaremos la directiva <code>plt.style</code> para elegir estilos estéticos apropiados para nuestras figuras. Aquí configuraremos el estilo <em>clásico</em>, que garantiza que los gráficos que creamos utilicen el estilo clásico de Matplotlib:</p>
<div id="c28e221c" class="cell">
<div class="sourceCode cell-code" id="cb2"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>plt.style.use(<span class="st">'classic'</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>A lo largo de esta sección, ajustaremos este estilo según sea necesario.</p>
<div id="88ddc83e" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb3"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> numpy <span class="im">as</span> np</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> np.linspace(<span class="dv">0</span>, <span class="dv">10</span>, <span class="dv">100</span>)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>fig <span class="op">=</span> plt.figure()</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x), <span class="st">'-'</span>)</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.cos(x), <span class="st">'--'</span>)</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>plt.show()<span class="op">;</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>En el ejemplo anterior, el comando <code>plt.show()</code> desencadena una serie de eventos que busca los objetos de figura activos y muestra las gráficas pendientes como imagen. Como por ejemplo en las siguientes dos celdas.</p>
<div id="8dbdce49-0db8-46d5-aec2-4e5ae0398233" class="cell">
<div class="sourceCode cell-code" id="cb4"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>fig <span class="op">=</span> plt.figure()</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x), <span class="st">'-'</span>)</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.cos(x), <span class="st">'--'</span>)<span class="op">;</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<div id="63ae0e5e-63de-4352-9414-8fe9e1973713" class="cell">
<div class="sourceCode cell-code" id="cb5"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> np.linspace(<span class="op">-</span><span class="dv">3</span>, <span class="dv">3</span>, <span class="dv">100</span>)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>fig <span class="op">=</span> plt.figure()</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.cos(x), <span class="st">'-'</span>)</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.cosh(x), <span class="st">'--'</span>)</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>plt.show()<span class="op">;</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="guardar-figuras-en-archivo" class="level3">
<h3 class="anchored" data-anchor-id="guardar-figuras-en-archivo">8.1.3 Guardar figuras en archivo</h3>
<p>Una característica interesante de Matplotlib es la capacidad de guardar figuras en una amplia variedad de formatos. Se puede guardar una figura utilizando el comando <code>savefig()</code>. Por ejemplo, para guardar la figura anterior como un archivo PNG o SVG, puede ejecutar esto:</p>
<div id="c8fd9635" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb6"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>fig.savefig(<span class="st">'my_figure.png'</span>)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>fig.savefig(<span class="st">'my_figure.svg'</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Para confirmar que contiene lo que creemos que contiene, usemos el objeto <code>Image</code> de IPython para mostrar el contenido de este archivo:</p>
<div id="4ce8cbab" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb7"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> IPython.display <span class="im">import</span> Image</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>Image(<span class="st">'my_figure.png'</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>En <code>savefig()</code>, el formato de archivo se infiere de la extensión del nombre de archivo dado. Dependiendo de los <em>backends</em> que tenga instalados, hay muchos formatos de archivos diferentes disponibles. La lista de tipos de archivos compatibles con su sistema se puede encontrar utilizando el siguiente método del objeto figura:</p>
<div id="9adea09e" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb8"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>fig.canvas.get_supported_filetypes()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Tenga en cuenta que al guardar su figura, no es necesario utilizar <code>plt.show()</code>.</p>
</section>
</section>
<section id="dos-interfaces-por-el-precio-de-una" class="level2">
<h2 class="anchored" data-anchor-id="dos-interfaces-por-el-precio-de-una">8.2 Dos interfaces por el precio de una</h2>
<p>Una característica de Matplotlib que puede resultar confusa es su interfaz dual: una interfaz basada en estados, al estilo de MATLAB, y una interfaz orientada a objetos más potente. Destacaremos rápidamente las diferencias entre ambas.</p>
<section id="interfaz-estilo-matlab" class="level3">
<h3 class="anchored" data-anchor-id="interfaz-estilo-matlab">8.2.1 Interfaz estilo MATLAB</h3>
<p>Matplotlib se escribió originalmente como una alternativa de Python para los usuarios de MATLAB y gran parte de su sintaxis refleja ese hecho. Las herramientas de estilo MATLAB están contenidas en la interfaz pyplot (<code>plt</code>). Por ejemplo, el siguiente código probablemente resultará bastante familiar para los usuarios de MATLAB:</p>
<div id="c7228c80" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb9"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>plt.figure() <span class="co"># crear una figura de trama</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Crea el primero de dos paneles y establece el eje actual.</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>plt.subplot(<span class="dv">2</span>, <span class="dv">1</span>, <span class="dv">1</span>) <span class="co"># (filas, columnas, número de panel)</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x))</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="co"># Crea el segundo panel y establece el eje actual.</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>plt.subplot(<span class="dv">2</span>, <span class="dv">1</span>, <span class="dv">2</span>)</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.cos(x))</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Es importante tener en cuenta que esta interfaz es <em>con estado</em>: realiza un seguimiento de la figura y los ejes ‘actuales’, que es donde se aplican todos los comandos <code>plt</code>. Puede obtener una referencia a estos utilizando las rutinas <code>plt.gcf()</code> (obtener la figura actual) y <code>plt.gca()</code> (obtener los ejes actuales).</p>
<p>Si bien esta interfaz con estado es rápida y conveniente para gráficos simples, es fácil tener problemas. Por ejemplo, una vez creado el segundo panel, ¿cómo podemos volver atrás y agregar algo al primero? Esto es posible dentro de la interfaz de estilo MATLAB, pero es un poco complicado. Afortunadamente, existe una manera más <em>pythonica</em>.</p>
</section>
<section id="interfaz-orientada-a-objetos" class="level3">
<h3 class="anchored" data-anchor-id="interfaz-orientada-a-objetos">8.2.2 Interfaz orientada a objetos</h3>
<p>La interfaz orientada a objetos está disponible para estas situaciones más complicadas y para cuando quieras tener más control sobre tu figura. En lugar de depender de alguna noción de una figura o ejes ‘activos’, en la interfaz orientada a objetos las funciones de trazado son <em>métodos</em> de objetos explícitos <code>figure</code> y <code>axis</code>. Para recrear el gráfico anterior utilizando este estilo de trazado, puedes hacer lo siguiente:</p>
<div id="325d9c18" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb10"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Primero crea una cuadrícula de gráficas</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="co"># ax será una matriz de dos objetos Axes</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>fig, ax <span class="op">=</span> plt.subplots(<span class="dv">2</span>)</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="co"># Llamar al método plot() en el objeto apropiado</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>ax[<span class="dv">0</span>].plot(x, np.sin(x))</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>ax[<span class="dv">1</span>].plot(x, np.cos(x))</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Para gráficas más simples, la elección del estilo a utilizar es en gran medida una cuestión de preferencia, pero el enfoque orientado a objetos puede volverse una necesidad a medida que las gráficas se vuelven más complicadas. A lo largo de este capítulo, alternaremos entre las interfaces de estilo MATLAB y las orientadas a objetos, dependiendo de lo que sea más conveniente. En la mayoría de los casos, la diferencia es tan pequeña como cambiar <code>plt.plot()</code> a <code>ax.plot()</code>, pero hay algunos problemas que destacaremos a medida que surjan en las siguientes secciones.</p>
</section>
</section>
<section id="gráficos-de-líneas-simples" class="level2">
<h2 class="anchored" data-anchor-id="gráficos-de-líneas-simples">8.3 Gráficos de líneas simples</h2>
<p>Quizás el más simple de todos los gráficos es la visualización de una única función <span class="math inline">\(y = f(x)\)</span>. Aquí daremos un primer vistazo a la creación de un gráfico sencillo de este tipo. Comenzaremos configurando el <em>notebook</em> para graficar. Primero, examinemos los estilos de gráficos que tiene disponible Matplotlib:</p>
<div id="4bec5616-cadf-4ef5-9a95-1845299a3e8b" class="cell">
<div class="sourceCode cell-code" id="cb11"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>mpl.style.available</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<div id="6e5b39e6" class="cell">
<div class="sourceCode cell-code" id="cb12"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span>matplotlib inline</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>plt.style.use(<span class="st">'ggplot'</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Para todos los gráficos de Matplotlib, comenzamos creando una figura y un eje. En su forma más simple, una figura y ejes se pueden crear de la siguiente manera:</p>
<div id="149c7a88" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb13"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>fig <span class="op">=</span> plt.figure()</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>ax <span class="op">=</span> plt.axes()</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>En Matplotlib, la <em>figura</em> (una instancia de la clase <code>plt.Figure</code>) puede considerarse como un contenedor único que contiene todos los objetos que representan ejes, gráficos, texto y etiquetas. Los <em>ejes</em> (una instancia de la clase <code>plt.Axes</code>) son lo que vemos arriba: un cuadro delimitador con marcas y etiquetas, que eventualmente contendrá los elementos del gráfico que componen nuestra visualización. A lo largo de este <em>Notebook</em>, utilizaremos comúnmente el nombre de variable ‘fig’ para referirnos a una instancia de figura, y ‘ax’ para referirnos a una instancia de ejes o un grupo de instancias de ejes.</p>
<p>Una vez que hemos creado los ejes, podemos utilizar la función <code>ax.plot</code> para representar gráficamente algunos datos. Empecemos con una sinusoide simple:</p>
<div id="7b024828" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb14"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>fig <span class="op">=</span> plt.figure()</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>ax <span class="op">=</span> plt.axes()</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> np.linspace(<span class="dv">0</span>, <span class="dv">10</span>, <span class="dv">1000</span>)</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>ax.plot(x, np.sin(x))<span class="op">;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Si queremos crear una sola figura con varias líneas, simplemente podemos llamar a la función <code>plot</code> varias veces:</p>
<div id="b431d656" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb15"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x))</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.cos(x))<span class="op">;</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>¡Eso es todo lo que hay que saber para trazar funciones simples en Matplotlib! Ahora profundizaremos en algunos detalles más sobre cómo controlar la apariencia de los ejes y las líneas.</p>
<section id="ajuste-de-colores-y-estilos-de-línea" class="level3">
<h3 class="anchored" data-anchor-id="ajuste-de-colores-y-estilos-de-línea">8.3.1 Ajuste de colores y estilos de línea</h3>
<p>El primer ajuste que quizás desees realizar en un gráfico es controlar los colores y estilos de línea. La función <code>plt.plot()</code> toma argumentos adicionales que pueden usarse para especificarlos. Para ajustar el color, puede utilizar la palabra clave <code>color</code>, que acepta un argumento de cadena que representa prácticamente cualquier color imaginable. El color se puede especificar de varias maneras:</p>
<div id="8b5a18f0" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb16"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x <span class="op">-</span> <span class="dv">0</span>), color<span class="op">=</span><span class="st">'blue'</span>) <span class="co"># especificar color por nombre</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x <span class="op">-</span> <span class="dv">1</span>), color<span class="op">=</span><span class="st">'g'</span>) <span class="co"># código de color corto (rgbcmyk)</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x <span class="op">-</span> <span class="dv">2</span>), color<span class="op">=</span><span class="st">'0.35'</span>) <span class="co"># Escala de grises entre 0 y 1</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x <span class="op">-</span> <span class="dv">3</span>), color<span class="op">=</span><span class="st">'#E15759'</span>) <span class="co"># Código hexadecimal (RRGGBB de 00 a FF)</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x <span class="op">-</span> <span class="dv">4</span>), color<span class="op">=</span>(<span class="fl">1.0</span>,<span class="fl">0.5</span>,<span class="fl">0.3</span>)) <span class="co"># Tupla RGB, valores 0 a 1</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x <span class="op">-</span> <span class="dv">5</span>), color<span class="op">=</span><span class="st">'cyan'</span>)<span class="op">;</span> <span class="co"># Se admiten todos los nombres de colores HTML</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>plt.legend([<span class="st">'Línea 1'</span>, <span class="st">'Línea 2'</span>,<span class="st">'Línea 3'</span>,<span class="st">'Línea 4'</span>, <span class="st">'Línea 5'</span>,<span class="st">'Línea 6'</span>])</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Para una lista de los nombres de colores disponibles consulte la <a href="https://matplotlib.org/stable/gallery/color/named_colors.html">documentación</a>.</p>
<p>Si no se especifica ningún color, Matplotlib recorrerá automáticamente un conjunto de colores predeterminados para varias líneas.</p>
<p>De manera similar, el estilo de línea se puede ajustar utilizando la palabra clave <code>linestyle</code>:</p>
<div id="a6f984c4" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb17"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">0</span>, linestyle<span class="op">=</span><span class="st">'solid'</span>)</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">1</span>, linestyle<span class="op">=</span><span class="st">'dashed'</span>)</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">2</span>, linestyle<span class="op">=</span><span class="st">'dashdot'</span>)</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">3</span>, linestyle<span class="op">=</span><span class="st">'dotted'</span>)<span class="op">;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a><span class="co"># Para abreviar, puedes utilizar los siguientes códigos:</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">4</span>, linestyle<span class="op">=</span><span class="st">'-'</span>) <span class="co"># sólido</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">5</span>, linestyle<span class="op">=</span><span class="st">'--'</span>) <span class="co"># discontinuo</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">6</span>, linestyle<span class="op">=</span><span class="st">'-.'</span>) <span class="co"># raya y punto</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">7</span>, linestyle<span class="op">=</span><span class="st">':'</span>)<span class="op">;</span> <span class="co"># punteado</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Si desea ser extremadamente conciso, estos códigos <code>linestyle</code> y <code>color</code> se pueden combinar en un solo argumento que no sea una palabra clave para la función <code>plt.plot()</code>:</p>
<div id="90137fa1" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb18"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">0</span>, <span class="st">'-g'</span>) <span class="co"># verde sólido</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">1</span>, <span class="st">'--c'</span>) <span class="co"># cian discontinuo</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">2</span>, <span class="st">'-.k'</span>) <span class="co"># raya negra</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>plt.plot(x, x <span class="op">+</span> <span class="dv">3</span>, <span class="st">':r'</span>)<span class="op">;</span> <span class="co"># punteado rojo</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Estos códigos de color de un solo carácter reflejan las abreviaturas estándar de los sistemas de color RGB (rojo/verde/azul) y CMYK (cian/magenta/amarillo/negro), comúnmente utilizados para gráficos en color digitales.</p>
<p>Hay muchos otros argumentos de palabras clave que se pueden usar para ajustar la apariencia del gráfico; para obtener más detalles, sugiero revisar la <a href="https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html">documentación</a> de la función <code>plt.plot()</code>.</p>
</section>
<section id="ajuste-de-límites-de-los-ejes" class="level3">
<h3 class="anchored" data-anchor-id="ajuste-de-límites-de-los-ejes">8.3.2 Ajuste de límites de los ejes</h3>
<p>Matplotlib hace un buen trabajo al elegir los límites de ejes predeterminados para su gráfico, pero a veces es bueno tener un control más preciso. La forma más básica de ajustar los límites de los ejes es utilizar los métodos <code>plt.xlim()</code> y <code>plt.ylim()</code>:</p>
<div id="d6d196be" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb19"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x))</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>plt.xlim(<span class="op">-</span><span class="dv">1</span>, <span class="dv">11</span>)</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>plt.ylim(<span class="op">-</span><span class="fl">1.5</span>, <span class="fl">1.5</span>)</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Si por alguna razón desea que alguno de los ejes se muestre al revés, puede simplemente invertir el orden de los argumentos:</p>
<div id="ba31d2c8" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb20"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x))</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>plt.xlim(<span class="dv">10</span>, <span class="dv">0</span>)</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>plt.ylim(<span class="fl">1.2</span>, <span class="op">-</span><span class="fl">1.2</span>)</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Un método relacionado útil es <code>plt.axis()</code> (note aquí la posible confusión entre <em>axes</em> con una <em>e</em> y <em>axis</em> con una <em>i</em>). El método <code>plt.axis()</code> le permite establecer los límites <code>x</code> y <code>y</code> con una sola llamada, pasando una lista que especifica <code>[xmin, xmax, ymin, ymax]</code>:</p>
<div id="6bda8654" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb21"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x))</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>plt.axis([<span class="op">-</span><span class="dv">1</span>, <span class="dv">11</span>, <span class="op">-</span><span class="fl">1.5</span>, <span class="fl">1.5</span>])</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>El método <code>plt.axis()</code> va incluso más allá de esto, permitiéndole hacer cosas como ajustar automáticamente los límites alrededor del gráfico actual:</p>
<div id="f666b759" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb22"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x))</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>plt.axis(<span class="st">'tight'</span>)</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Permite especificaciones de nivel aún más alto, como garantizar una relación de aspecto igual para que en la pantalla, una unidad en «x» sea igual a una unidad en «y»:</p>
<div id="449e9593" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb23"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x))</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>plt.axis(<span class="st">'equal'</span>)</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Para obtener más información sobre los límites de los ejes y otras capacidades del método <code>plt.axis</code>, consulte su <a href="https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.axis.html">documentación</a>.</p>
</section>
<section id="etiquetas" class="level3">
<h3 class="anchored" data-anchor-id="etiquetas">8.3.4 Etiquetas</h3>
<p>Como última parte de esta sección, veremos brevemente el etiquetado de los gráficos: títulos, etiquetas de ejes y leyendas simples.</p>
<p>Los títulos y las etiquetas de los ejes son las etiquetas más simples; existen métodos que se pueden usar para configurarlas rápidamente:</p>
<div id="bed9e162" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb24"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x))</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>plt.title(<span class="st">'Curva seno'</span>)</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>plt.xlabel(<span class="st">'x'</span>)</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>plt.ylabel(<span class="st">'sen(x)'</span>)</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>La posición, el tamaño y el estilo de estas etiquetas se pueden ajustar utilizando argumentos opcionales para la función. Para obtener más información, consulte la documentación de Matplotlib .</p>
<p>Cuando se muestran varias líneas dentro de un solo eje, puede ser útil crear una leyenda de gráfico que etiquete cada tipo de línea. Nuevamente, Matplotlib tiene una forma incorporada de crear rápidamente dicha leyenda. Esto se hace a través del método (lo adivinaste) <code>plt.legend()</code>. Si bien existen varias formas válidas de utilizar esto, me resulta más fácil especificar la etiqueta de cada línea utilizando la palabra clave <code>label</code> de la función plot:</p>
<div id="c985f43d" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb25"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x), <span class="st">'-g'</span>, label<span class="op">=</span><span class="st">'sin(x)'</span>)</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.cos(x), <span class="st">':b'</span>, label<span class="op">=</span><span class="st">'cos(x)'</span>)</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>plt.axis(<span class="st">'equal'</span>)</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>plt.legend()</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Como puede ver, la función <code>plt.legend()</code> realiza un seguimiento del estilo y el color de la línea y los combina con la etiqueta correcta. Puede encontrar más información sobre cómo especificar y formatear leyendas de gráficos en la documentación <code>plt.legend</code>.</p>
<p>Adicionalmente, Matplotlib permite establecer etiquetas y leyendas usando intérprete de LateX:</p>
<div id="185e1fda-8835-45fd-9383-d096a1f41678" class="cell">
<div class="sourceCode cell-code" id="cb26"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.sin(x), <span class="st">'--g'</span>, label<span class="op">=</span><span class="vs">r'$\sin(x)$'</span>)</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>plt.plot(x, np.cos(x), <span class="st">'-.b'</span>, label<span class="op">=</span><span class="vs">r'$\cos(x)$'</span>)</span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>plt.axis(<span class="st">'equal'</span>)</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>plt.xticks(fontsize<span class="op">=</span><span class="dv">14</span>)</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>plt.yticks(fontsize<span class="op">=</span><span class="dv">14</span>)</span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a>plt.legend(fontsize<span class="op">=</span><span class="dv">20</span>)</span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="problemas-con-matplotlib" class="level3">
<h3 class="anchored" data-anchor-id="problemas-con-matplotlib">8.3.5Problemas con Matplotlib</h3>
<p>Si bien la mayoría de las funciones <code>plt</code> se traducen directamente a métodos <code>ax</code> (como <code>plt.plot()</code> → <code>ax.plot()</code>, <code>plt.legend()</code> → <code>ax.legend()</code>, etc.), este no es el caso de todos los comandos. En particular, se modifican ligeramente las funciones para establecer límites, etiquetas y títulos. Para realizar la transición entre funciones de estilo MATLAB y métodos orientados a objetos, realice los siguientes cambios:</p>
<ul>
<li><code>plt.xlabel()</code> → <code>ax.set_xlabel()</code></li>
<li><code>plt.ylabel()</code> → <code>ax.set_ylabel()</code></li>
<li><code>plt.xlim()</code> → <code>ax.set_xlim()</code></li>
<li><code>plt.ylim()</code> → <code>ax.set_ylim()</code></li>
<li><code>plt.title()</code> → <code>ax.set_title()</code></li>
</ul>
<p>En la interfaz orientada a objetos para trazar gráficos, en lugar de llamar a estas funciones individualmente, a menudo es más conveniente utilizar el método <code>ax.set()</code> para configurar todas estas propiedades a la vez:</p>
<div id="ab3199e1" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb27"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>ax <span class="op">=</span> plt.axes()</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>ax.plot(x, np.sin(x))</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>ax.<span class="bu">set</span>(xlim<span class="op">=</span>(<span class="dv">0</span>, <span class="dv">10</span>), ylim<span class="op">=</span>(<span class="op">-</span><span class="dv">2</span>, <span class="dv">2</span>),</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a> xlabel<span class="op">=</span><span class="st">'$x$'</span>, ylabel<span class="op">=</span><span class="vs">r'$\sin(x)$'</span>,</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a> title<span class="op">=</span><span class="st">'Gráfica simple'</span>)</span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
</section>
<section id="diagramas-de-dispersión-simples" class="level2">
<h2 class="anchored" data-anchor-id="diagramas-de-dispersión-simples">8.4 Diagramas de dispersión simples</h2>
<p>Otro tipo de gráfico comúnmente utilizado es el gráfico de dispersión simple, un primo cercano del gráfico lineal. En lugar de unir los puntos mediante segmentos de línea, aquí los puntos se representan individualmente con un punto, un círculo u otra forma.</p>
<section id="diagramas-de-dispersión-con-plt.plot" class="level3">
<h3 class="anchored" data-anchor-id="diagramas-de-dispersión-con-plt.plot">8.4.1 Diagramas de dispersión con <code>plt.plot</code></h3>
<p>En la sección anterior, analizamos <code>plt.plot</code>/<code>ax.plot</code> para producir gráficos lineales. Resulta que esta misma función también puede producir gráficos de dispersión:</p>
<div id="854a8232" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb28"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> np.linspace(<span class="dv">0</span>, <span class="dv">10</span>, <span class="dv">30</span>)</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> np.sin(x)</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>plt.plot(x, y, <span class="st">'ok'</span>)</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>El tercer argumento en la llamada de función es un carácter que representa el tipo de símbolo utilizado para el gráfico. Así como se pueden especificar opciones como <code>'-'</code>, <code>'--'</code> para controlar el estilo de línea, el estilo de marcador tiene su propio conjunto de códigos de cadena cortos. La lista completa de símbolos disponibles se puede ver en la documentación de <code>plt.plot</code>, o en la documentación en línea de Matplotlib. La mayoría de las posibilidades son bastante intuitivas, y aquí mostraremos algunas de las más comunes:</p>
<div id="9ecc223e" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb29"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>rng <span class="op">=</span> np.random.RandomState(<span class="dv">0</span>)</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>plt.figure(figsize<span class="op">=</span>(<span class="dv">12</span>,<span class="dv">6</span>))</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> marker <span class="kw">in</span> [<span class="st">'o'</span>, <span class="st">'.'</span>, <span class="st">','</span>, <span class="st">'x'</span>, <span class="st">'+'</span>, <span class="st">'v'</span>, <span class="st">'^'</span>, <span class="st">'<'</span>, <span class="st">'>'</span>, <span class="st">'s'</span>, <span class="st">'d'</span>]:</span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a> plt.plot(rng.rand(<span class="dv">5</span>), rng.rand(<span class="dv">5</span>), marker,</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a> label<span class="op">=</span><span class="ss">f'marker=</span><span class="sc">{</span>marker<span class="sc">}</span><span class="ss">'</span>)</span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>plt.legend(loc<span class="op">=</span><span class="st">'center left'</span>, bbox_to_anchor<span class="op">=</span>(<span class="dv">1</span>, <span class="fl">0.5</span>),numpoints<span class="op">=</span><span class="dv">1</span>)</span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>plt.xlim(<span class="dv">0</span>, <span class="fl">1.1</span>)</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Para obtener aún más posibilidades, estos códigos de caracteres se pueden utilizar junto con códigos de línea y color para trazar puntos junto con una línea que los conecta:</p>
<div id="f7caa30f" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb30"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, y, <span class="st">'-ok'</span>)</span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Los argumentos de palabras clave adicionales a <code>plt.plot</code> especifican una amplia gama de propiedades de las líneas y marcadores:</p>
<div id="53e3af1b" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb31"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, y, <span class="st">'-p'</span>, color<span class="op">=</span><span class="st">'gray'</span>,</span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a> markersize<span class="op">=</span><span class="dv">12</span>, linewidth<span class="op">=</span><span class="dv">4</span>,</span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a> markerfacecolor<span class="op">=</span><span class="st">'cyan'</span>,</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a> markeredgecolor<span class="op">=</span><span class="st">'gray'</span>,</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a> markeredgewidth<span class="op">=</span><span class="dv">2</span>)</span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>plt.ylim(<span class="op">-</span><span class="fl">1.2</span>, <span class="fl">1.2</span>)</span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Este tipo de flexibilidad en la función <code>plt.plot</code> permite una amplia variedad de posibles opciones de visualización. Para obtener una descripción completa de las opciones disponibles, consulte la documentación de <code>plt.plot</code>.</p>
</section>
<section id="diagramas-de-dispersión-con-plt.scatter" class="level3">
<h3 class="anchored" data-anchor-id="diagramas-de-dispersión-con-plt.scatter">8.4.2 Diagramas de dispersión con <code>plt.scatter</code></h3>
<p>Un segundo método más potente para crear gráficos de dispersión es la función <code>plt.scatter</code>, que se puede utilizar de forma muy similar a la función <code>plt.plot</code>:</p>
<div id="5a0627e8" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb32"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>plt.scatter(x, y, marker<span class="op">=</span><span class="st">'o'</span>)</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>La principal diferencia entre <code>plt.scatter</code> y <code>plt.plot</code> es que se puede utilizar para crear gráficos de dispersión donde las propiedades de cada punto individual (tamaño, color de la cara, color del borde, etc.) se pueden controlar individualmente o asignar a los datos.</p>
<p>Demostremos esto creando un gráfico de dispersión aleatorio con puntos de muchos colores y tamaños. Para ver mejor los resultados superpuestos, también usaremos la palabra clave <code>alpha</code> para ajustar el nivel de transparencia:</p>
<div id="5efd1dc1" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb33"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>rng <span class="op">=</span> np.random.RandomState(<span class="dv">0</span>)</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> rng.randn(<span class="dv">100</span>)</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> rng.randn(<span class="dv">100</span>)</span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>colors <span class="op">=</span> rng.rand(<span class="dv">100</span>)</span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>sizes <span class="op">=</span> <span class="dv">1000</span> <span class="op">*</span> rng.rand(<span class="dv">100</span>)</span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>plt.figure(figsize<span class="op">=</span>(<span class="dv">12</span>,<span class="dv">12</span>))</span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>plt.scatter(x, y, c<span class="op">=</span>colors, s<span class="op">=</span>sizes, alpha<span class="op">=</span><span class="fl">0.5</span>,</span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a> cmap<span class="op">=</span><span class="st">'inferno'</span>)</span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>plt.colorbar()</span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Tenga en cuenta que el argumento de color se asigna automáticamente a una escala de color (mostrada aquí por el comando <code>colorbar()</code>) y que el argumento de tamaño se da en píxeles. De esta manera, el color y el tamaño de los puntos se pueden utilizar para transmitir información en la visualización, con el fin de visualizar datos multidimensionales.</p>
<p>Por ejemplo, podríamos utilizar los datos de Iris de Scikit-Learn, donde cada muestra es uno de los tres tipos de flores a las que se les ha medido cuidadosamente el tamaño de sus pétalos y sépalos:</p>
<div id="62dee087" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb34"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> sklearn.datasets <span class="im">import</span> load_iris</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>iris <span class="op">=</span> load_iris()</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>features <span class="op">=</span> iris.data.T</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>plt.scatter(features[<span class="dv">0</span>], features[<span class="dv">1</span>], alpha<span class="op">=</span><span class="fl">0.6</span>,</span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a> s<span class="op">=</span><span class="dv">200</span><span class="op">*</span>features[<span class="dv">2</span>], c<span class="op">=</span>iris.target, cmap<span class="op">=</span><span class="st">'magma'</span>)</span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>plt.xlabel(iris.feature_names[<span class="dv">0</span>])</span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a>plt.ylabel(iris.feature_names[<span class="dv">1</span>])</span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Podemos ver que este diagrama de dispersión nos ha dado la capacidad de explorar simultáneamente cuatro dimensiones diferentes de los datos: La ubicación <span class="math inline">\((x, y)\)</span> de cada punto corresponde a la longitud y el ancho del sépalo, el tamaño del punto está relacionado con el largo del pétalo y el color está relacionado con la especie particular de flor. Los gráficos de dispersión multicolores y de múltiples características como éste pueden ser útiles tanto para la exploración como para la presentación de datos.</p>
</section>
<section id="plot-versus-scatter-una-nota-sobre-la-eficiencia" class="level3">
<h3 class="anchored" data-anchor-id="plot-versus-scatter-una-nota-sobre-la-eficiencia">8.4.3 <code>plot</code> versus <code>scatter</code>: una nota sobre la eficiencia</h3>
<p>Además de las diferentes funciones disponibles en <code>plt.plot</code> y <code>plt.scatter</code>, ¿por qué elegiría utilizar uno en lugar del otro? Si bien no es tan importante para pequeñas cantidades de datos, a medida que los conjuntos de datos se hacen más grandes que unos pocos miles de puntos, <code>plt.plot</code> puede ser notablemente más eficiente que <code>plt.scatter</code>. La razón es que <code>plt.scatter</code> tiene la capacidad de renderizar un tamaño y/o color diferente para cada punto, por lo que el renderizador debe hacer el trabajo adicional de construir cada punto individualmente. En <code>plt.plot</code>, por otro lado, los puntos son siempre esencialmente clones unos de otros, por lo que el trabajo de determinar la apariencia de los puntos se realiza solo una vez para todo el conjunto de datos. Para conjuntos de datos grandes, la diferencia entre estos dos puede generar un rendimiento muy diferente y, por este motivo, se debería preferir <code>plt.plot</code> sobre <code>plt.scatter</code> para conjuntos de datos grandes.</p>
</section>
</section>
<section id="visualizando-errores" class="level2">
<h2 class="anchored" data-anchor-id="visualizando-errores">8.5 Visualizando errores</h2>
<p>En cualquier medición científica, la contabilización precisa de los errores es casi tan importante, si no más, que la información precisa del número en sí. Por ejemplo, imaginemos que tenemos algunas observaciones astrofísicas para estimar la Constante de Hubble, la medida local de la tasa de expansión del Universo.</p>
<p>Sé que la literatura actual sugiere un valor de alrededor de 71 (km/s)/Mpc, y mido un valor de 74 (km/s)/Mpc con mi método. ¿Son consistentes los valores? La única respuesta correcta, dada esta información, es esta: no hay forma de saberlo.</p>
<p>Supongamos que amplío esta información con las incertidumbres reportadas: la literatura actual sugiere un valor de alrededor de 71 <span class="math inline">\(\pm\)</span> 2.5 (km/s)/Mpc, y mi método ha medido un valor de 74 <span class="math inline">\(\pm\)</span> 5 (km/s)/Mpc. Ahora bien, ¿son consistentes los valores? Esa es una pregunta que puede responderse cuantitativamente.</p>
<p>En la visualización de datos y resultados, mostrar estos errores de manera efectiva puede hacer que un gráfico transmita información mucho más completa.</p>
<p>Se puede crear una barra de error básica con una sola llamada a la función Matplotlib:</p>
<div id="a879b0f9" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb35"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> np.linspace(<span class="dv">0</span>, <span class="dv">10</span>, <span class="dv">50</span>)</span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>dy <span class="op">=</span> <span class="fl">0.1</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> np.sin(x) <span class="op">+</span> dy <span class="op">*</span> np.random.randn(<span class="dv">50</span>)</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>plt.errorbar(x, y, yerr<span class="op">=</span>dy, fmt<span class="op">=</span><span class="st">'.k'</span>)</span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Aquí, <code>fmt</code> es un código de formato que controla la apariencia de líneas y puntos, y tiene la misma sintaxis que la abreviatura utilizada en <code>plt.plot</code>.</p>
<p>Además de estas opciones básicas, la función <code>errorbar</code> tiene muchas opciones para ajustar las salidas. Usando estas opciones adicionales puedes personalizar fácilmente la estética de tu gráfico con barras de error.</p>
<div id="a591ff5e" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb36"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a>plt.errorbar(x, y, yerr<span class="op">=</span>dy, fmt<span class="op">=</span><span class="st">'o'</span>, color<span class="op">=</span><span class="st">'red'</span>,</span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a> ecolor<span class="op">=</span><span class="st">'darkgray'</span>, elinewidth<span class="op">=</span><span class="dv">3</span>, capsize<span class="op">=</span><span class="dv">5</span>)</span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Además de estas opciones, también puede especificar barras de error horizontales (<code>xerr</code>), barras de error unilaterales y muchas otras variantes. Para obtener más información sobre las opciones disponibles, consulte la documentación de <code>plt.errorbar</code>.</p>
</section>
<section id="gráficas-de-densidad-y-contorno" class="level2">
<h2 class="anchored" data-anchor-id="gráficas-de-densidad-y-contorno">8.6 Gráficas de densidad y contorno</h2>
<p>A veces es útil mostrar datos tridimensionales en dos dimensiones utilizando contornos o regiones codificadas por colores. Hay tres funciones de Matplotlib que pueden ser útiles para esta tarea: <code>plt.contour</code> para gráficos de contorno, <code>plt.contourf</code> para gráficos de contorno rellenos y <code>plt.imshow</code> para mostrar imágenes.</p>
<p>Comenzaremos demostrando un gráfico de contorno usando una función <span class="math inline">\(z = f(x, y)\)</span>, usando la siguiente opción particular para <span class="math inline">\(f\)</span>:</p>
<div id="6387de06-4847-41a9-a862-d307d870e675" class="cell">
<div class="sourceCode cell-code" id="cb37"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> f(x, y):</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> np.sin(x) <span class="op">**</span> <span class="dv">10</span> <span class="op">+</span> np.cos(<span class="dv">10</span> <span class="op">+</span> y <span class="op">*</span> x) <span class="op">*</span> np.cos(x)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Se puede crear un gráfico de contorno con la función <code>plt.contour</code>. Toma tres argumentos: una cuadrícula de valores <em>x</em>, una cuadrícula de valores <em>y</em> y una cuadrícula de valores <em>z</em>. Los valores <em>x</em> e <em>y</em> representan posiciones en el gráfico, y los valores <em>z</em> estarán representados por los niveles de contorno. Quizás la forma más sencilla de preparar dichos datos es utilizar la función <code>np.meshgrid</code>, que construye cuadrículas bidimensionales a partir de matrices unidimensionales:</p>
<div id="0a40127a" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb38"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> np.linspace(<span class="dv">0</span>, <span class="dv">5</span>, <span class="dv">50</span>)</span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> np.linspace(<span class="dv">0</span>, <span class="dv">5</span>, <span class="dv">40</span>)</span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a>X, Y <span class="op">=</span> np.meshgrid(x, y)</span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a>Z <span class="op">=</span> f(X, Y)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Ahora veamos esto con un gráfico de contorno de solo líneas estándar:</p>
<div id="f00235a8" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb39"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>plt.contour(X, Y, Z, colors<span class="op">=</span><span class="st">'black'</span>)</span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Tenga en cuenta que, de forma predeterminada, cuando se utiliza un solo color, los valores negativos se representan mediante líneas discontinuas y los valores positivos, mediante líneas continuas. Alternativamente, las líneas pueden codificarse por colores especificando un mapa de colores con el argumento <code>cmap</code>. Aquí también especificaremos que queremos que se dibujen más líneas: 20 intervalos igualmente espaciados dentro del rango de datos:</p>
<div id="24e370ed" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb40"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>plt.contour(X, Y, Z, <span class="dv">20</span>, cmap<span class="op">=</span><span class="st">'RdGy'</span>)</span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Aquí elegimos el mapa de colores «RdGy» (abreviatura de <em>Rojo-Gris</em>), que es una buena opción para datos centrados. Matplotlib tiene una amplia gama de mapas de colores disponibles, que puedes explorar fácilmente en IPython completando una tabulación en el módulo <code>plt.cm</code>:</p>
<pre><code>plt.cm.<TAB></code></pre>
<p>Nuestra gráfica se ve mejor, pero los espacios entre las líneas pueden distraer un poco. Podemos cambiar esto cambiando a un gráfico de contorno relleno usando la función <code>plt.contourf()</code> (observe la <code>f</code> al final), que utiliza en gran medida la misma sintaxis que <code>plt.contour()</code>.</p>
<p>Además, agregaremos un comando <code>plt.colorbar()</code>, que crea automáticamente un eje adicional con información de color etiquetada para el gráfico:</p>
<div id="728c8088" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb42"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a>plt.contourf(X, Y, Z, <span class="dv">20</span>, cmap<span class="op">=</span><span class="st">'RdGy'</span>)</span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>plt.colorbar()</span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>La barra de colores deja claro que las regiones negras son ‘picos’, mientras que las regiones rojas son ‘valles’.</p>
<p>Un problema potencial con este gráfico es que es un poco irregular, es decir, los pasos de color son discretos en lugar de continuos, lo que no siempre es lo deseado. Esto se podría remediar estableciendo el número de contornos en un número muy alto, pero el resultado es un gráfico bastante ineficiente: Matplotlib debe representar un nuevo polígono para cada paso del nivel. Una mejor manera de manejar esto es usar la función <code>plt.imshow()</code>, que interpreta una cuadrícula bidimensional de datos como una imagen.</p>
<p>El siguiente código lo muestra:</p>
<div id="a8f2a71c" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb43"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a>plt.imshow(Z, extent<span class="op">=</span>[<span class="dv">0</span>, <span class="dv">5</span>, <span class="dv">0</span>, <span class="dv">5</span>], origin<span class="op">=</span><span class="st">'lower'</span>,cmap<span class="op">=</span><span class="st">'RdGy'</span>)</span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>plt.colorbar()</span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>plt.axis()</span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Sin embargo, existen algunos problemas potenciales con <code>imshow()</code>:</p>
<ul>
<li><code>plt.imshow()</code> no acepta una cuadrícula <em>x</em> e <em>y</em>, por lo que debe especificar manualmente la <em>extensión</em> [<em>xmin</em>, <em>xmax</em>, <em>ymin</em>, <em>ymax</em>] de la imagen en el gráfico.</li>
<li><code>plt.imshow()</code> sigue de manera predeterminada la definición de matriz de imágenes estándar, donde el origen está en la esquina superior izquierda, no en la esquina inferior izquierda como en la mayoría de los gráficos de contorno. Esto se debe cambiar cuando se muestran datos en cuadrícula.</li>
</ul>
<p>Por último, a veces puede resultar útil combinar gráficos de contorno y gráficos de imágenes. Por ejemplo, aquí utilizaremos una imagen de fondo parcialmente transparente (con la transparencia establecida a través del parámetro <code>alpha</code>) y superpondremos los contornos con etiquetas en los contornos mismos (utilizando la función <code>plt.clabel()</code>):</p>
<div id="365bb66d" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb44"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a>contours <span class="op">=</span> plt.contour(X, Y, Z, <span class="dv">3</span>, colors<span class="op">=</span><span class="st">'black'</span>)</span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>plt.clabel(contours, inline<span class="op">=</span><span class="va">True</span>, fontsize<span class="op">=</span><span class="dv">10</span>)</span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a>plt.imshow(Z, extent<span class="op">=</span>[<span class="dv">0</span>, <span class="dv">5</span>, <span class="dv">0</span>, <span class="dv">5</span>], origin<span class="op">=</span><span class="st">'lower'</span>,</span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a> cmap<span class="op">=</span><span class="st">'RdGy'</span>, alpha<span class="op">=</span><span class="fl">0.5</span>)</span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>plt.colorbar()</span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>La combinación de estas tres funciones (<code>plt.contour</code>, <code>plt.contourf</code> y <code>plt.imshow</code>) ofrece posibilidades casi ilimitadas para mostrar este tipo de datos tridimensionales dentro de un gráfico bidimensional.</p>
</section>
<section id="histogramas-binnings-y-densidad" class="level2">
<h2 class="anchored" data-anchor-id="histogramas-binnings-y-densidad">8.7 Histogramas, binnings y densidad</h2>
<p>Un histograma simple puede ser un gran primer paso para comprender un conjunto de datos.</p>
<div id="4d128f64-4555-4e68-99a2-be1f52a8c1af" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb45"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a>data <span class="op">=</span> np.random.randn(<span class="dv">1000</span>)</span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a>plt.hist(data)</span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>La función <code>hist()</code> tiene muchas opciones para ajustar tanto el cálculo como la visualización; He aquí un ejemplo de un histograma más personalizado:</p>
<div id="0edfc1c4" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb46"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a>plt.hist(data, bins<span class="op">=</span><span class="dv">30</span>, density<span class="op">=</span><span class="va">True</span>, alpha<span class="op">=</span><span class="fl">0.5</span>,</span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a> histtype<span class="op">=</span><span class="st">'stepfilled'</span>, color<span class="op">=</span><span class="st">'steelblue'</span>,</span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a> edgecolor<span class="op">=</span><span class="st">'none'</span>)</span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>La cadena de documentación <code>plt.hist</code> tiene más información sobre otras opciones de personalización disponibles.</p>
<div id="5e21a6f1" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb47"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>x1 <span class="op">=</span> np.random.normal(<span class="dv">0</span>, <span class="fl">0.8</span>, <span class="dv">1000</span>)</span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a>x2 <span class="op">=</span> np.random.normal(<span class="op">-</span><span class="dv">2</span>, <span class="dv">1</span>, <span class="dv">1000</span>)</span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a>x3 <span class="op">=</span> np.random.normal(<span class="dv">3</span>, <span class="dv">2</span>, <span class="dv">1000</span>)</span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a>kwargs <span class="op">=</span> <span class="bu">dict</span>(histtype<span class="op">=</span><span class="st">'stepfilled'</span>, alpha<span class="op">=</span><span class="fl">0.3</span>, density<span class="op">=</span><span class="va">False</span>, bins<span class="op">=</span><span class="dv">40</span>)</span>
<span id="cb47-6"><a href="#cb47-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-7"><a href="#cb47-7" aria-hidden="true" tabindex="-1"></a>plt.hist(x1, <span class="op">**</span>kwargs)</span>
<span id="cb47-8"><a href="#cb47-8" aria-hidden="true" tabindex="-1"></a>plt.hist(x2, <span class="op">**</span>kwargs)</span>
<span id="cb47-9"><a href="#cb47-9" aria-hidden="true" tabindex="-1"></a>plt.hist(x3, <span class="op">**</span>kwargs)</span>
<span id="cb47-10"><a href="#cb47-10" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<section id="histogramas-y-binnings-bidimensionales" class="level3">
<h3 class="anchored" data-anchor-id="histogramas-y-binnings-bidimensionales">8.7.1 Histogramas y binnings bidimensionales</h3>
<p>Así como creamos histogramas en una dimensión dividiendo la línea numérica en contenedores, también podemos crear histogramas en dos dimensiones dividiendo puntos entre contenedores bidimensionales. Echaremos un vistazo breve a varias formas de hacer esto aquí. Comenzaremos definiendo algunos datos: una matriz extraída de una distribución gaussiana multivariada:</p>
<div id="bfe03566" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb48"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a>mean <span class="op">=</span> [<span class="dv">0</span>, <span class="dv">0</span>]</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>cov <span class="op">=</span> [[<span class="dv">1</span>, <span class="dv">1</span>], [<span class="dv">1</span>, <span class="dv">2</span>]]</span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a>x, y <span class="op">=</span> np.random.multivariate_normal(mean, cov, <span class="dv">10000</span>).T</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<section id="plt.hist2d-histograma-bidimensional" class="level4">
<h4 class="anchored" data-anchor-id="plt.hist2d-histograma-bidimensional"><code>plt.hist2d</code>: Histograma bidimensional</h4>
<p>Una forma sencilla de trazar un histograma bidimensional es utilizar la función <code>plt.hist2d</code> de Matplotlib:</p>
<div id="4f4e6de8" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb49"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a>plt.hist2d(x, y, bins<span class="op">=</span><span class="dv">30</span>, cmap<span class="op">=</span><span class="st">'Blues'</span>)</span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>cb <span class="op">=</span> plt.colorbar()</span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>cb.set_label(<span class="st">'Frecuencia'</span>)</span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Al igual que con <code>plt.hist</code>, <code>plt.hist2d</code> tiene una serie de opciones adicionales para ajustar el gráfico y el binning, que están muy bien delineadas en la cadena de documentación de la función.</p>
</section>
<section id="plt.hexbin-agrupamientos-hexagonales" class="level4">
<h4 class="anchored" data-anchor-id="plt.hexbin-agrupamientos-hexagonales"><code>plt.hexbin</code>: Agrupamientos hexagonales</h4>
<p>El histograma bidimensional crea una teselación de cuadrados a lo largo de los ejes. Otra forma natural para tal teselación es el hexágono regular. Para este propósito, Matplotlib proporciona la rutina <code>plt.hexbin</code>, que representará un conjunto de datos bidimensionales agrupados dentro de una cuadrícula de hexágonos:</p>
<div id="d2f97948" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb50"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a>plt.hexbin(x, y, gridsize<span class="op">=</span><span class="dv">30</span>, cmap<span class="op">=</span><span class="st">'Blues'</span>)</span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>cb <span class="op">=</span> plt.colorbar(label<span class="op">=</span><span class="st">'Frecuencia'</span>)</span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p><code>plt.hexbin</code> tiene varias opciones interesantes, incluida la capacidad de especificar pesos para cada punto y cambiar la salida en cada contenedor a cualquier agregado NumPy (media de pesos, desviación estándar de pesos, etc.).</p>
</section>
</section>
</section>
<section id="personalización-de-leyendas" class="level2">
<h2 class="anchored" data-anchor-id="personalización-de-leyendas">8.8 Personalización de leyendas</h2>
<p>Las leyendas de la gráfica dan significado a una visualización, asignando significado a los diversos elementos de la trama.</p>
<p>Anteriormente vimos cómo crear una leyenda simple; aquí veremos cómo personalizar la ubicación y la estética de la leyenda en Matplotlib.</p>
<p>La leyenda más simple se puede crear con el comando <code>plt.legend()</code>, que crea automáticamente una leyenda para cualquier elemento gráfico etiquetado:</p>
<div id="119ce7da" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb51"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a>x <span class="op">=</span> np.linspace(<span class="dv">0</span>, <span class="dv">10</span>, <span class="dv">1000</span>)</span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>fig, ax <span class="op">=</span> plt.subplots()</span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a>ax.plot(x, np.sin(x), <span class="st">'-b'</span>, label<span class="op">=</span><span class="st">'Seno'</span>)</span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a>ax.plot(x, np.cos(x), <span class="st">'--r'</span>, label<span class="op">=</span><span class="st">'Coseno'</span>)</span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a>ax.axis(<span class="st">'equal'</span>)</span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a>leg <span class="op">=</span> ax.legend()</span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Pero hay muchas formas en las que podríamos personalizar dicha leyenda. Por ejemplo, podemos especificar la ubicación y desactivar el marco:</p>
<div id="cada82a3" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb52"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a>ax.legend(loc<span class="op">=</span><span class="st">'upper left'</span>, frameon<span class="op">=</span><span class="va">False</span>)</span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a>fig</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Podemos usar el comando <code>ncol</code> para especificar el número de columnas en la leyenda:</p>
<div id="0c86d5f5" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb53"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a>ax.legend(frameon<span class="op">=</span><span class="va">False</span>, loc<span class="op">=</span><span class="st">'lower center'</span>, ncol<span class="op">=</span><span class="dv">2</span>)</span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a>fig</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Podemos utilizar un cuadro redondeado (<code>fancybox</code>) o agregar una sombra, cambiar la transparencia (valor alfa) del marco o cambiar el relleno alrededor del texto:</p>
<div id="6be60b4c" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb54"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a>ax.legend(fancybox<span class="op">=</span><span class="va">True</span>, framealpha<span class="op">=</span><span class="dv">1</span>, shadow<span class="op">=</span><span class="va">True</span>, borderpad<span class="op">=</span><span class="dv">1</span>)</span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a>fig</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Para obtener más información sobre las opciones de leyenda disponibles, consulte la cadena de documentación <code>plt.legend</code>.</p>
<section id="elección-de-elementos-para-la-leyenda" class="level3">
<h3 class="anchored" data-anchor-id="elección-de-elementos-para-la-leyenda">8.8.1 Elección de elementos para la leyenda</h3>
<p>Como ya hemos visto, la leyenda incluye todos los elementos etiquetados por defecto. Si esto no es lo deseado, podemos ajustar qué elementos y etiquetas aparecen en la leyenda utilizando los objetos devueltos por los comandos de trazado. El comando <code>plt.plot()</code> puede crear varias líneas a la vez y devuelve una lista de instancias de líneas creadas. Al pasar cualquiera de estos a <code>plt.legend()</code> le indicaremos cuál identificar, junto con las etiquetas que nos gustaría especificar:</p>
<div id="64621ba9" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb55"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> np.sin(x[:, np.newaxis] <span class="op">+</span> np.pi <span class="op">*</span> np.arange(<span class="dv">0</span>, <span class="dv">2</span>, <span class="fl">0.5</span>))</span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>lines <span class="op">=</span> plt.plot(x, y)</span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a>plt.legend(lines[:<span class="dv">2</span>], [<span class="st">'1°'</span>, <span class="st">'2°'</span>])</span>
<span id="cb55-5"><a href="#cb55-5" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Generalmente, en la práctica encuentro que es más claro utilizar el primer método, aplicando etiquetas a los elementos del gráfico que desea mostrar en la leyenda:</p>
<div id="67bcb61d" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb56"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a>plt.plot(x, y[:, <span class="dv">0</span>], label<span class="op">=</span><span class="st">'1°'</span>)</span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>plt.plot(x, y[:, <span class="dv">1</span>], label<span class="op">=</span><span class="st">'2°'</span>)</span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a>plt.plot(x, y[:, <span class="dv">2</span>:])</span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a>plt.legend(framealpha<span class="op">=</span><span class="dv">1</span>, frameon<span class="op">=</span><span class="va">True</span>)</span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Tenga en cuenta que, de forma predeterminada, la leyenda ignora todos los elementos sin un atributo <code>label</code> establecido y aquellas etiquetas que inician con <code>_</code></p>
</section>
<section id="leyenda-del-tamaño-de-los-puntos" class="level3">
<h3 class="anchored" data-anchor-id="leyenda-del-tamaño-de-los-puntos">8.8.2 Leyenda del tamaño de los puntos</h3>
<p>A veces, los valores predeterminados de la leyenda no son suficientes para la visualización dada. Por ejemplo, quizás esté utilizando el tamaño de los puntos para marcar ciertas características de los datos y desee crear una leyenda que refleje esto. A continuación se muestra un ejemplo en el que utilizaremos el tamaño de los puntos para indicar las poblaciones de las ciudades de California. Nos gustaría una leyenda que especifique la escala de los tamaños de los puntos, y lograremos esto trazando algunos datos etiquetados sin entradas:</p>
<div id="068f038d" class="cell" data-jupyter="{"outputs_hidden":false}">
<div class="sourceCode cell-code" id="cb57"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> pandas <span class="im">as</span> pd</span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a><span class="cf">try</span>:</span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a> cities <span class="op">=</span> pd.read_csv(<span class="st">'california_cities.csv'</span>)</span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a><span class="cf">except</span>:</span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a> <span class="op">!</span>curl <span class="op">-</span>O https:<span class="op">//</span>raw.githubusercontent.com<span class="op">/</span>jakevdp<span class="op">/</span>PythonDataScienceHandbook<span class="op">/</span>master<span class="op">/</span>notebooks_v1<span class="op">/</span>data<span class="op">/</span>california_cities.csv </span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a> cities <span class="op">=</span> pd.read_csv(<span class="st">'california_cities.csv'</span>)</span>
<span id="cb57-7"><a href="#cb57-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-8"><a href="#cb57-8" aria-hidden="true" tabindex="-1"></a><span class="co"># Extraer los datos que nos interesan</span></span>
<span id="cb57-9"><a href="#cb57-9" aria-hidden="true" tabindex="-1"></a>lat, lon <span class="op">=</span> cities[<span class="st">'latd'</span>], cities[<span class="st">'longd'</span>]</span>
<span id="cb57-10"><a href="#cb57-10" aria-hidden="true" tabindex="-1"></a>population, area <span class="op">=</span> cities[<span class="st">'population_total'</span>], cities[<span class="st">'area_total_km2'</span>]</span>
<span id="cb57-11"><a href="#cb57-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-12"><a href="#cb57-12" aria-hidden="true" tabindex="-1"></a><span class="co"># Distribuye los puntos, usando tamaño y color pero sin etiqueta</span></span>
<span id="cb57-13"><a href="#cb57-13" aria-hidden="true" tabindex="-1"></a>plt.scatter(lon, lat, label<span class="op">=</span><span class="va">None</span>,</span>
<span id="cb57-14"><a href="#cb57-14" aria-hidden="true" tabindex="-1"></a> c<span class="op">=</span>np.log10(population), cmap<span class="op">=</span><span class="st">'viridis'</span>,</span>
<span id="cb57-15"><a href="#cb57-15" aria-hidden="true" tabindex="-1"></a> s<span class="op">=</span>area, linewidth<span class="op">=</span><span class="dv">0</span>, alpha<span class="op">=</span><span class="fl">0.5</span>)</span>
<span id="cb57-16"><a href="#cb57-16" aria-hidden="true" tabindex="-1"></a>plt.axis(<span class="st">'equal'</span>)</span>
<span id="cb57-17"><a href="#cb57-17" aria-hidden="true" tabindex="-1"></a>plt.xlabel(<span class="st">'longitude'</span>)</span>
<span id="cb57-18"><a href="#cb57-18" aria-hidden="true" tabindex="-1"></a>plt.ylabel(<span class="st">'latitude'</span>)</span>
<span id="cb57-19"><a href="#cb57-19" aria-hidden="true" tabindex="-1"></a>plt.colorbar(label<span class="op">=</span><span class="st">'log$_</span><span class="sc">{10}</span><span class="st">$(population)'</span>)</span>
<span id="cb57-20"><a href="#cb57-20" aria-hidden="true" tabindex="-1"></a>plt.clim(<span class="dv">3</span>, <span class="dv">7</span>)</span>
<span id="cb57-21"><a href="#cb57-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-22"><a href="#cb57-22" aria-hidden="true" tabindex="-1"></a><span class="co"># Aquí creamos una leyenda:</span></span>
<span id="cb57-23"><a href="#cb57-23" aria-hidden="true" tabindex="-1"></a><span class="co"># Trazaremos listas vacías con el tamaño y la etiqueta deseados</span></span>
<span id="cb57-24"><a href="#cb57-24" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> area <span class="kw">in</span> [<span class="dv">100</span>, <span class="dv">300</span>, <span class="dv">500</span>]:</span>
<span id="cb57-25"><a href="#cb57-25" aria-hidden="true" tabindex="-1"></a> plt.scatter([], [], c<span class="op">=</span><span class="st">'k'</span>, alpha<span class="op">=</span><span class="fl">0.3</span>, s<span class="op">=</span>area,</span>
<span id="cb57-26"><a href="#cb57-26" aria-hidden="true" tabindex="-1"></a> label<span class="op">=</span><span class="bu">str</span>(area) <span class="op">+</span> <span class="st">' km$^2$'</span>)</span>
<span id="cb57-27"><a href="#cb57-27" aria-hidden="true" tabindex="-1"></a>plt.legend(scatterpoints<span class="op">=</span><span class="dv">1</span>, frameon<span class="op">=</span><span class="va">False</span>, labelspacing<span class="op">=</span><span class="dv">1</span>, title<span class="op">=</span><span class="st">'Área de la ciudad'</span>)</span>
<span id="cb57-28"><a href="#cb57-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-29"><a href="#cb57-29" aria-hidden="true" tabindex="-1"></a>plt.title(<span class="st">'Ciudades de California: Área y Población'</span>)</span>
<span id="cb57-30"><a href="#cb57-30" aria-hidden="true" tabindex="-1"></a>plt.show()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>La leyenda siempre hará referencia a algún objeto que esté en el gráfico, por lo que si queremos mostrar una forma particular, necesitaremos trazarla. En este caso, los objetos que queremos (círculos grises) no están en el gráfico, por lo que los falsificamos trazando listas vacías. Tenga en cuenta también que la leyenda solo enumera los elementos de la trama que tienen una etiqueta especificada.</p>