0% encontró este documento útil (0 votos)
253 vistas

Pythonhydro Español

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
253 vistas

Pythonhydro Español

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 127

Machine Translated by Google

Machine Translated by Google

Pitón
en hidrología

Versión 0.0.0

Sat Kumar Tomer


Machine Translated by Google

Copyright © 2011 Sat Kumar Tomer.

Historial de impresión:

Noviembre 2011: Primera edición de Python en Hidrología.

Se otorga permiso para copiar, distribuir y/o modificar este documento bajo los términos de la Licencia de Documentación
Libre de GNU, Versión 1.1 o cualquier versión posterior publicada por la Free Software Foundation; sin secciones invariantes,
sin textos de portada y sin textos de contraportada.

La licencia de documentación libre de GNU está disponible en www.gnu.org o escribiendo a Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307, EE. UU.

La forma original de este libro es el código fuente de LATEX. La compilación de esta fuente LATEX tiene el efecto de generar
una representación independiente del dispositivo de un libro de texto, que se puede convertir a otros formatos e imprimir.
Machine Translated by Google
Machine Translated by Google

Prefacio

Historia
Empecé a usar Python en julio de 2010. Estaba buscando un lenguaje de programación que fuera de
código abierto y pudiera combinar muchos códigos/módulos/software. Me encontré con Python y Perl,
aunque podría haber muchas más opciones disponibles. Busqué en Google el uso de Python y Perl en el
campo del uso científico general, la hidrología, el Sistema de Información Geográfica (SIG), las estadísticas
y, de alguna manera, descubrí que Python era el lenguaje que necesitaba. No sé si mis conclusiones sobre
Python versus Perl eran ciertas o no. Pero me siento feliz de que Python sea mi elección, y está cumpliendo
con mis requisitos.

Después de usar Python durante dos o tres meses, me aficioné al código abierto y comencé a usar solo
software de código abierto, me despedí de Windows, ArcGis, MATLAB. E incluso después de un año, no
los extraño. Sentí que también debía hacer una pequeña contribución al mundo libre. Traté de contribuir
en algunas áreas, pero no pude seguir adelante debido a mi menor conocimiento en esas áreas. Después
de pasar un año extenso con Python, pensé en hacer alguna contribución al mundo de Python. Escribí
algunos paquetes pequeños para Python y comencé a escribir este libro.

Siempre me ha dado miedo leer libros, especialmente los que tienen más de 200 páginas. No recuerdo si
he leído algún libro completo que tuviera más de 200 páginas. Aunque la lista de libros que he leído es
muy pequeña, incluso para los libros que tenían menos de 200 páginas. No me gusta mucho el texto del
libro y me gusta aprender de los ejemplos del libro. Soy un estudiante, no un profesor, por lo que no tengo
idea de lo que les gusta a los estudiantes, excepto mi propio sentimiento que sé que a muchos de mis
compañeros no les gusta.

Espero que encuentre este libro útil y agradable.

Sat Kumar Tomer


Bangalore, India

Sat Kumar Tomer es estudiante de doctorado en el departamento de ingeniería civil del Instituto Indio de
Ciencias, Bangalore, India.
Machine Translated by Google

vi Capítulo 0. Prefacio

Agradecimientos
Le agradezco que haya leído el libro y espero recibir sus comentarios.

Agradezco a Allen B. Downey que proporcionó el código fuente de látex de sus libros, lo que me ayudó a formatear el
libro de una mejor manera. Aparte de eso, ha escrito una buena historia para su libro titulado 'Think Python: How to Think
Like a Computer Scientist', lo que me animó a escribir este libro. Y copié muchas oraciones de su libro, principalmente lo
básico sobre Python.

Agradezco a la Free Software Foundation por desarrollar la Licencia de Documentación Libre GNU.

Estoy agradecido con Green Tea Press.

Estoy agradecido con mis amigos Aditya Singh, Ganjendara Yadav, Himanshu Joshi, Katarina Turcekova, Shadi Davarian
y Shobhit Khatyan por su continuo apoyo.

Lista de colaboradores

Si tiene alguna sugerencia o corrección, envíe un correo electrónico a [email protected]. Si realizo un cambio
basado en sus comentarios, lo agregaré a la lista de colaboradores (a menos que solicite ser omitido).

Si incluye al menos parte de la oración en la que aparece el error, eso me facilita la búsqueda.
Los números de página y sección también están bien, pero no es tan fácil trabajar con ellos. ¡Gracias!
Machine Translated by Google

Contenido

Prefacio v

1 Primeros pasos 1

1.1 ¿Por qué Python? . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . .... 1

1.2 Instalación de Python . . . . . . . . . . . . ... . . . . . . . . . . . . . . .... 1

1.3 Instalar paquetes adicionales. . . . . . . . . . . . . . . . . . . . . . . . . .... 2

1.4 Entorno de desarrollo interactivo. . ... . . . . . . . . . . . . . . .... 3

1.5 Ejecutar el programa. . . . . . . . . . . ... . . . . . . . . . . . . . . .... 4

1.6 Tipo de errores . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . .... 4

1.7 El primer programa. . . . . . . . . . . . . ... . . . . . . . . . . . . . . .... 5

2 Un poco de Python 7

2.1 Tipo de datos. . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . .... 7

2.2 Estructuras de datos . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . ....9

2.3 Estructuras de datos . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . ....9

2.4 Elección del nombre de la variable. . . . . . ... . . . . . . . . . . . . . . .... 12

2.5 Operadores y operandos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.6 expresiones . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 15

2.7 Flujo de control . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 15

2.8 Función .... . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 18

2.9 Graficado . . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 20

3 matriz 21

3.1 Generación de arreglos secuenciales. . . . . . . . . . . . . . . . . . . . . . . . .... 21

3.2 Atributos y métodos útiles . . . . . . . ... . . . . . . . . . . . . . . . . . . 23

3.3 Indexación. . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 25

3.4 Manipulación de matriz. . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 26


Machine Translated by Google

viii Contenido

4 Aplicaciones básicas en Hidrología 29

4.1 Introducción . . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 29

4.2 Vapor de agua. . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 29

4.3 Precipitación. . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 30

4.4 Lluvia . . . . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 31

4.5 Evaporación . . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 34

4.6 Infiltración . . . . . . . . . . . . . . . . . . . . . . . . . . ..... . . . . . . . 38

4.7 Superficie del agua . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 39

4.8 Método de enrutamiento fluvial-Muskingum . . . . . . . . . . . . . . . . . . . . . . . . . 41

5 Estadísticas 43

5.1 Distribuciones empíricas . . . . . . . . . . . . . . . . . . . ..... . . . . . . . 43

5.2 Distribuciones teóricas . ..... . . . . . . . . . . . . ..... . . . . . . . 48

5.3 La prueba t . . . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 54

5.4 Prueba KS . . . . . . . . . . . . . . . . . . . . . . . . . . . . ..... . . . . . . . 55

5.5 La prueba de chi cuadrado . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 55

5.6 Medida de dependencia estadística. . . . . . . . . . . . . ..... . . . . . . . 56

5.7 Regresión lineal. . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 59

5.8 Regresión polinomial. . . ..... . . . . . . . . . . . . ..... . . . . . . . 60

5.9 Interpolación. . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 61

5.10 Autocorrelación . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 63

5.11 Intervalos de incertidumbre. . . . . . . . . . . . . . . . . . . . ..... . . . . . . . 66

6 Datos espaciales 69

6.1 Tipos de datos espaciales . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 69

6.2 Geoinformación. . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 72

6.3 Ráster de escritura . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 72

6.4 Vector de escritura. . . . . . . . . . . . . . . . . . . . . . . . ..... . . . . . . . 73

6.5 Lectura del ráster . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 74

6.6 Leer el vector. . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 75

6.7 Filtrado. . . . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 75

6.8 NDVI. . . . . . . . . . . ..... . . . . . . . . . . . . ..... . . . . . . . 77


Machine Translated by Google

Contenido ix

7 Trazado 81

7.1 Eje de fecha .... . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 81

7.2 Gráficos de barras ... . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 82

7.3 Gráficos circulares ... . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 83

7.4 Parcelas 2D . . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 84

7.5 parcelas en 3D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

7.6 Diagrama de caja. . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 88

7.7 Gráfica QQ . . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 89

7.8 trama . . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 90

7.9 Anotación .. . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 92

7.10 Mapa base. . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 92

7.11 Eje compartido .. . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 94

7.12 Subtrama. . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 95

8 Entrada-Salida 99

8.1 xls . . . . . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 99

8.2 Archivo de texto .... . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 101

8.3 NetCDF. . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 102

8.4 Pepinillo ..... . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 104

9 Modelado Numérico 105

9.1 Integración. . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 105

9.2 ODA. ..... . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 106

9.3 Estimación de parámetros . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 107

10 Estadísticas avanzadas 111

10.1 cópula. . . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . .... 111

10.2 Distribución multivariada . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 113

Una biblioteca de instalación 115

A.1 Mapa base. . . . . . . . . . . . . . . . . . ... . . . . . . . . . . . . . . . . . . 115


Machine Translated by Google

X Contenido
Machine Translated by Google

Capítulo 1

Empezando

1.1 ¿Por qué Python?

Python es un lenguaje de programación simple y poderoso. Por simple quiero decir que es mucho más indulgente que lenguajes
como C, aunque también es lento. Por poderoso, quiero decir que puede pegar fácilmente muchos códigos existentes que
fueron escritos en C, C++, Fortran, etc. Esto tiene una comunidad de usuarios en crecimiento que hace que muchas
herramientas estén fácilmente disponibles. Python Package Index, que es un anfitrión importante del código Python, tiene más
de 15,000 paquetes en la lista, lo que habla de su popularidad. El uso de Python en la comunidad de hidrología no es tan rápido
en comparación con otros campos, pero actualmente se están desarrollando muchos paquetes hidrológicos nuevos. Python
proporciona acceso a una buena combinación de herramientas GIS, Matemáticas, Estadísticas, etc., lo que lo convierte en un
lenguaje útil para el hidrólogo. Las siguientes son las principales ventajas de Python para el hidrólogo:

1. Una sintaxis clara y legible.

2. Los módulos se pueden escribir fácilmente en C, C++.

3. Se puede usar en todas las plataformas principales (Windows, Linux/Unix, Mac, etc.)

4. Fácil de aprender.

5. Y es gratis.

1.2 Instalación de Python

Por lo general, todo el sistema Linux/Unix tiene Python por defecto. Si no está allí, o para usuarios que no son de Linux/Unix,
la versión básica de Python se puede descargar siguiendo las instrucciones que se proporcionan a continuación.
La versión básica de Python incluye los paquetes mínimos necesarios para ejecutar Python y algunos otros paquetes
adicionales. Para la mayoría de las aplicaciones hidrológicas, estos paquetes no son suficientes y necesitamos paquetes
adicionales. En la siguiente sección, describiré cómo instalar paquetes adicionales. A lo largo del libro, el cheurón (>>>)
representa el shell de Python, y $ representa el shell de Unix/Linux o la línea de comandos de la ventana. La instalación de
Python para los distintos sistemas operativos se realiza de la siguiente manera.
Machine Translated by Google

2 Capítulo 1. Primeros pasos

1.2.1 Ubuntu/Debian
En Ubunt/Debian, Python se instala ejecutando el comando de instalación habitual, es decir:

$ sudo apt-get install python

1.2.2 Fedora
En Fedora, la instalación de Python se realiza de la siguiente manera.

$ sudo yum instalar python

1.2.3 FreeBSD
Python se instala en FreeBSD ejecutando:

$ sudo pkg_add instalar python

El usuario de Linux puede estar familiarizado con sudo. Permite al usuario ejecutar programas con los privilegios
de seguridad de raíz o administrador. El usuario de Windows puede ignorar sudo, ya que no necesita especificar esto.

1.2.4 Ventanas
Para usuarios de Windows, la versión adecuada de Python se puede descargar desde http://www.python.
org/getit/. Proporciona un archivo .msi, que se puede instalar fácilmente haciendo doble clic en él.

1.2.5 Sistema operativo Mac

Los usuarios de Mac OS también pueden descargar una versión adecuada de Python desde http://
www.python.org/getit/ e instalarla.

1.3 Instalar paquetes adicionales


Pip es un programa útil para instalar paquetes adicionales en Python. Antes de instalar pip, se debe instalar
la distribución. Para hacerlo, primero debemos descargar Distribute, que se realiza descargando el archivo
distribuir_setup.py desde http://python-distribute.org/distribute_setup.py y ejecutando el siguiente comando:

$ sudo python distribuir_setup.py

Ahora descargue get-pip.py desde https://github.com/pypa/pip/raw/master/contrib/ get-pip.py y ejecútelo


como root:

$ sudo python get-pip.py


Machine Translated by Google

1.4. Entorno de desarrollo interactivo 3

Tenga en cuenta que distribuir_setup.py y get-pip.py deben estar en su directorio de trabajo actual durante la
instalación; de lo contrario, proporcione el nombre completo de la ruta del archivo. Si no obtuvo ningún error en
este procedimiento, pip debería estar listo para instalar nuevos paquetes. El procedimiento para instalar paquetes
es simple, por ejemplo, suponga que desea instalar el paquete SomePackage, luego ejecute el siguiente comando:

$ sudo pip instalar algún paquete

En hidrología, los paquetes de uso frecuente son Numpy, Scipy, xlrd, xlwt y gdal, por lo que deben instalarse en
esta etapa. Más adelante, siempre que se necesite un nuevo paquete/biblioteca, se darán instrucciones para
descargarlos allí.

$ sudo pip install Numpy $ sudo


pip install Scipy $ sudo pip install
xlrd $ sudo pip install xlwt $ sudo
pip install gdal

Estos paquetes/bibliotecas se pueden instalar especificando el nombre de todos los paquetes en una línea, es
decir, $ sudo pip install Numpy Scipy xlrd xlwt gdal. Pero, en este momento, es mejor instalarlos en una línea
separada, de modo que si obtiene algún error, pueda averiguar fácilmente qué paquete está dando error.
El problema más común con pip es que no puede descargar la biblioteca/paquete de Internet. En ese caso, puede
descargar la biblioteca *.tar.gz usando el navegador de Internet y luego ejecutar el pip de la siguiente manera:

$ sudo pip install /ruta/a/*.tar.gz

Además, el usuario de la ventana puede descargar el archivo *.exe o *.msi si está disponible y luego descargarlo
haciendo doble clic en él.

Si esto también falla, como última opción, puede descargar el archivo *.tar.gz y extraerlo. Luego, vaya a la carpeta
donde extrajo el archivo. Debería ver el archivo setup.py allí. Ahora, ejecuta el siguiente comando:

$ sudo python setup.py instalar

Si ve algún error en esto, posiblemente se deba a que algún paquete/biblioteca dependiente no está disponible en
su computadora. Debe leer el archivo README provisto con el paquete, puede brindarle detalles del paquete/
biblioteca requeridos y cómo instalarlos.

Los paquetes/bibliotecas se actualizan usando el pip de la siguiente manera.

$ sudo pip install --actualizar algún_paquete

1.4 Entorno de desarrollo interactivo


Se pueden usar editores de texto simples para escribir programas de Python, pero estos no brindan opciones para
formatear fácilmente el texto, opciones de depuración, etc. IDE (Entorno de desarrollo interactivo) brinda muchas
opciones para formatear rápidamente el programa en forma de Python y depurarlos fácilmente. Existen
Machine Translated by Google

4 Capítulo 1. Primeros pasos

varios IDE disponibles para su uso, por ejemplo, PyDev, Spyder, IDLE y muchos otros. Puede encontrar una lista
de ellos en http://wiki.python.org/moin/IntegratedDevelopmentEnvironments. Estoy usando Spyder para mi trabajo,
que es similar a MATLAB. La razón para usar Spyder fue que antes trabajaba en MATLAB, y Spyder es similar, y
descubrí que estaba familiarizado con él.
Sin embargo, puede usar cualquier IDE y, después de familiarizarse, no importa cuál use.

1.5 Ejecutar el programa


Python es un lenguaje interpretado ya que los programas son ejecutados por un intérprete. Hay dos formas de
usar el intérprete: modo interactivo y modo script. En el modo interactivo, escribe programas de Python (después
de invocar python, lo que se hace escribiendo python en una terminal o ventana de comandos) y el intérprete
imprime el resultado, por ejemplo, hacemos 1+1 en él.

>>> 1 + 1
2

El cheurón, >>>, es el indicador que utiliza el intérprete para indicar que está listo. Si escribe 1 + 1, el intérprete
responde 2. Alternativamente, puede almacenar código en un archivo y usar el intérprete para ejecutar el
contenido del archivo, lo que se denomina secuencia de comandos. Por convención, los scripts de Python tienen
nombres que terminan con .py. Suponga que ha nombrado su secuencia de comandos como myscript.py, y desea
ejecutarla, en un shell de Unix/Linux, haría lo siguiente:

$ python myscript.py

o bien, puede otorgar permiso de ejecución a su secuencia de comandos y simplemente ejecutar la secuencia de comandos. La sintaxis a realizar es:

$ chmod +x miscript.py $ ./
myscript.py

En los IDE, los detalles de ejecución de scripts son diferentes. Puede encontrar instrucciones para su entorno en
el sitio web de Python python.org.

Trabajar en modo interactivo es conveniente para probar pequeños fragmentos de código porque puede escribirlos
y ejecutarlos inmediatamente. Pero para algo más que unas pocas líneas, debe guardar su código como un script
para que pueda modificarlo y ejecutarlo en el futuro.

1.6 Tipo de errores


Pueden ocurrir tres tipos de errores en un programa: errores de sintaxis, errores de tiempo de ejecución y errores
semánticos. Es útil distinguirlos para localizarlos más rápidamente.

1.6.1 Errores de sintaxis

Python solo puede ejecutar un programa si la sintaxis es correcta; de lo contrario, el intérprete muestra un mensaje
de error. La sintaxis se refiere a la estructura de un programa y las reglas sobre esa estructura. Por ejemplo, los
paréntesis deben venir en pares coincidentes, por lo que (1 + 2) es legal, pero 8) es una sintaxis .
error.
Machine Translated by Google

1.7. el primer programa 5

1.6.2 Errores de tiempo de ejecución

El segundo tipo de error es un error de tiempo de ejecución, llamado así porque el error no aparece hasta
que el programa ha comenzado a ejecutarse. Estos errores también se denominan excepciones porque
suelen indicar que ha ocurrido algo excepcional (y malo).

1.6.3 Errores semánticos

El tercer tipo de error es el error semántico. Si hay un error semántico en su programa, se ejecutará con
éxito en el sentido de que la computadora no generará ningún mensaje de error, pero no hará lo correcto.

1.7 El primer programa


Tradicionalmente, el primer programa que escribes en un nuevo idioma se llama "¡Hola, mundo!" porque todo
lo que hace es mostrar las palabras "¡Hola, mundo!". En Python, se ve así:

>>> imprimir '¡Hola, mundo!'

Este es un ejemplo de una declaración de impresión, que en realidad no imprime nada en papel. Muestra un
valor en la pantalla. En este caso, el resultado son las palabras:

¡Hola Mundo!

Las comillas en el programa marcan el principio y el final de la cadena.


Machine Translated by Google

6 Capítulo 1. Primeros pasos


Machine Translated by Google

Capitulo 2

Un poco de pitón

Antes de saltar a la aplicación de Python en hidrología, lo que implicaría escribir muchas líneas de codificación,
manipular matrices, etc. Es mejor aprender algunos conceptos básicos de Python, por ejemplo, los tipos de
datos, bucles (realizar la misma tarea muchas veces) y escribir funciones, etc. Lo primero que debe saber es
el tipo de datos.

2.1 Tipo de datos

Hay básicamente dos tipos de datos; números y cadenas. La función de tipo devuelve el tipo de datos.

2.1.1 Números
Hay tres tipos de números en Python: enteros, coma flotante y números complejos. Los números enteros son
necesarios para indexar las matrices (vector, matriz), para contar, etc. En Python no es necesario definir el
tipo de variable a priori, y se permite incluso cambiar el tipo de datos más adelante en el programa, donde sea
necesario.

>>> un = 5
>>> tipo(a)
<tipo 'int'>

Esto significa que el tipo de datos es entero. Las líneas en el programa sin cheurón (>>>) representan la salida
de Python. Otro tipo de datos más utilizado es el flotante. La mayoría de las variables hidrológicas pertenecen
a esta categoría de tipo de datos.

>>> b = 7.8
>>> tipo(b)
<tipo 'flotante'>

Esto significa que el tipo de datos es punto flotante. Otro tipo de datos es complejo, que no se necesita con
frecuencia en la vida hidrológica del día a día.
Machine Translated by Google

8 Capítulo 2. Un poco de Python

>>> c = 5 + 2j >>>
tipo(c) <tipo
'complejo'>

La c representa el tipo de datos complejo.

2.1.2 Cadenas
Una cadena es una secuencia de caracteres. Hay tres formas de especificar una cadena.

comillas simples: Python trata el texto escrito dentro de comillas simples como una cadena.

>>> foo = 'mi nombre es Joe' >>>


print(foo) mi nombre es Joe

comillas dobles: Las comillas dobles también se utilizan para definir una cadena. Si las comillas simples pueden
definir, ¿por qué se necesitan comillas dobles? Tratemos de escribir ¿Cuál es tu nombre? utilizando comillas simples.

>>> foo = '¿cuál es tu nombre?'


Archivo "<stdin>", línea 1 foo =
'¿cómo te llamas?'
ˆ

Error de sintaxis: sintaxis invalida

Esto produce SyntaxError. Intentemos usar comillas dobles.

>>> foo = "¿cuál es tu nombre?" >>>


print(foo) ¿cómo te llamas?

Las comillas dobles proporcionan una manera fácil de definir cadenas que incluyen comillas simples. Sin
embargo, la misma tarea también se puede realizar utilizando comillas simples. La misma cadena se puede
escribir usando comillas simples usando \ antes de .'

>>> foo = '¿cuál es tu nombre?' >>> print(foo)


¿cómo te llamas?

comillas triples: cuando las cadenas abarcan más de una línea, las comillas triples son las mejores para definirlas.
Las cadenas de varias líneas también se pueden especificar usando la secuencia de escape \n en cadenas
de comillas simples o dobles, las comillas triples facilitan la escritura. Las comillas triples también son útiles
para otras cosas (hacer contenido de ayuda para funciones), que leerá más adelante en el libro.

>>> foo = """Mi nombre es Sat Kumar.


... estoy en doctorado """

>>> print foo Mi


nombre es Sat Kumar.
estoy en doctorado
Machine Translated by Google

2.2. Estructuras de datos 9

2.2 Estructuras de datos

Las estructuras de datos pueden contener más de un dato. Hay cuatro estructuras de datos integradas en Python: lista, tupla,

diccionario y conjunto. Además de esta estructura de datos incorporada, puede definir su propio tipo de datos también como
numpy.array definido por numpy, lo cual es muy útil. No sentí ninguna necesidad de usar el conjunto en hidrología, por lo que
me saltearé el conjunto aquí, si está interesado, puede obtener información sobre él de alguna otra fuente.

2.3 Estructuras de datos

2.3.1 Lista

Una lista es una secuencia de elementos (valores). Los elementos que contiene pueden pertenecer a cualquier tipo de datos y pueden
ser de diferentes tipos de datos en la misma lista.

>>> a = ['Carnero', 'Sita', 'Bangalore', 'Delhi'] >>> b = [25, 256, 2656, 0]


>>> c = [25, 'Bangalore']

Se accede a los elementos de la lista mediante los índices. Las variables a y b contienen elementos de tipos de datos
similares, mientras que c contiene elementos de diferentes tipos de datos. En Python, los índices comienzan en 0. Entonces,
para obtener el primer y el tercer elemento, los índices deben ser 0 y 2.

>>> a = ['Ram', 'Sita', 'Bangalore', 'Delhi'] >>> print a[0]

RAM
>>> imprime un[2]
Bangalore

Los índices negativos también están permitidos en Python. El último elemento de la lista tiene índices de -1, de manera similar, el penúltimo
elemento tiene índices de -2 y así sucesivamente.

>>> a = ['Ram', 'Sita', 'Bangalore', 'Delhi'] >>> print a[-1]

Delhi

Asimismo, se puede acceder al penúltimo elemento de la lista utilizando los índices -2.

2.3.2 Diccionario
En la lista, los índices son solo números enteros. Dictionary tiene la capacidad de tomar cualquier tipo de datos como índices.
Esta característica del diccionario lo hace muy adecuado cuando los índices son nombres, etc. Por ejemplo, en hidrología se
dan los nombres de las estaciones de campo y sus correspondientes variables para cada estación. Intentemos recuperar el
valor de la variable usando primero la lista y luego usando el diccionario. Podemos usar una lista para almacenar el nombre
de las estaciones y otra para la variable. Primero, necesitamos encontrar los índices de la estación y luego usar estos índices
para acceder a la variable desde la lista de variables.
Machine Translated by Google

10 Capítulo 2. Un poco de Python

>>> nombres = ['Delhi', 'Bangalore', 'Kolkata'] >>> precipitaciones =


[0, 5, 10] >>> print(precipitaciones[ind]) 5

Ahora, intentemos esto usando el diccionario.

>>> lluvia = {'Delhi':0, 'Bangalore':5, 'Kolkata':10} >>> lluvia['Bangalore'] 5

Se podría haber hecho lo mismo usando la lista en una línea, pero el diccionario proporciona una forma ordenada y
limpia de hacerlo.

2.3.3 Tupla
Una tupla es una secuencia de valores, similar a una lista, excepto que las tuplas son inmutables (su valor no se
puede modificar).

>>> foo = 5,15,18 >>>


foo[2]
5
>>> foo[1] = 10
Rastreo (llamadas recientes más última):
Archivo "<stdin>", línea 1, en <módulo>
TypeError: el objeto 'tupla' no admite la asignación de elementos

Al intentar modificar los elementos de la tupla, Python emite un error. Las tuplas son útiles, es necesario especificar
algunas constantes y asegurarse de que estas constantes no cambien. La propiedad inmutable de las tuplas asegura
que durante las ejecuciones del programa el valor de las constantes no cambiará.

Una tupla que tiene solo un elemento se define usando ',' después de esto, por ejemplo:

>>> fo = 5
>>> tipo(foo) <tipo
'int'> >>> foo = 5,
>>> tipo(foo) <tipo
'tupla'>

Es posible que haya notado que sin usar la coma ('), Python no lo toma como una tupla.

2.3.4 Numpy.matriz
NumericalPython (NumPy) es una biblioteca/paquete escrito principalmente en lenguaje de programación C, pero se
proporciona una interfaz de programación de aplicaciones (API) para Python. La biblioteca proporcionó el tipo de
datos numpy.array, que es muy útil para realizar operaciones matemáticas en una matriz. Es el tipo de datos que
estaríamos tratando la mayor parte del tiempo. Esta biblioteca no es parte del Python estándar
Machine Translated by Google

2.3. Estructuras de datos 11

distribución, por lo tanto, antes de usar esto, NumPy debe estar instalado en el sistema. Podemos verificar si NumPy
está instalado en nuestro sistema o no, usando el siguiente comando:

$ python -c'importar número'

Si este comando no da ningún resultado (ningún error), significa que NumPy está instalado. Si NumPy no está
instalado en el sistema, verá un mensaje (error) como el siguiente:

$ python -c'importar número'


Rastreo (llamadas recientes más última):
Archivo "<cadena>", línea 1, en <módulo>
ImportError: ningún módulo llamado numpy

Esto significa que numpy no está instalado en el sistema. Puede instalar NumPy siguiendo los pasos proporcionados
en la sección 1.3. El python -c'import numpy' es una forma de ejecutar un código simple sin invocar el python. Esto
es útil cuando desea hacer algo pequeño rápidamente. Esto es muy útil cuando desea verificar si algún paquete
está instalado o no en su sistema.

Antes de usar cualquier biblioteca, debe importarse al programa. La importación se puede utilizar para importar la
biblioteca. Hay tres formas de importar una biblioteca completa o algunas funciones de la biblioteca. Importando la
biblioteca completa.

>>> import numpy >>>


x = [1, 2, 5, 9.0, 15] # lista que contiene solo números (flotantes o enteros) >>> type(x) <type 'list'> >>> x =
numpy .array(x) # convierte la lista en una matriz numpy >>> type(x) <type 'numpy.ndarray'>

Importamos la biblioteca completa numpy y, después de hacerlo, siempre que necesitemos una función (es decir,
una matriz) de esta biblioteca, debemos proporcionar el nombre junto con el nombre de la biblioteca (es decir,
numpy.array). La función de matriz convierte una lista de enteros o flotantes en una matriz numpy. A menudo, el
nombre de la biblioteca es bastante largo y se puede abreviar usando como de la siguiente manera.

>>> import numpy as np >>> x


= np.array(x) # convierte la lista en una matriz numpy >>> type(x) <type
'numpy.ndarray'>

Si solo se necesitan unas pocas funciones, se pueden importar definiendo explícitamente su nombre.

>>> from numpy import array >>> x =


array(x) # convertir la lista en numpy array >>> type(x) <type 'numpy.ndarray'>

Si se necesitan todas las funciones y no desea usar numpy o np antes de ellas, puede importar de la siguiente
manera.
Machine Translated by Google

12 Capítulo 2. Un poco de Python

>>> from numpy import * >>> x =


arreglo(x) # convertir la lista en arreglo numpy >>> type(x) <type
'numpy.ndarray'>

Todo lo que se escribe después de # es un comentario para el programa y Python no lo ejecuta. Los comentarios
son útiles para hacer que su código sea más legible. Los comentarios también pueden estar en línea completa.
Una matriz numpy es una matriz multidimensional homogénea. Solo puede contener enteros, solo flotantes,
combinación de enteros y flotantes, números complejos y cadenas. Si se especifica una combinación de enteros y
flotantes en numpy.ndarray, los enteros se tratan como flotantes. El tipo de datos de numpy.ndarray se puede
verificar usando su atributo dtype.

>>> import numpy as np >>> x


= np.array([1,5,9.0,15]) # np.array también se puede definir directamente >>> x.dtype dtype('float64')
>>> x = np.array([1,5,9,15]) # esto contiene solo números enteros >>> x.dtype dtype('int64') >>> x =
np.array(['Delhi', 'Paris ']) # esto contiene cadenas >>> x.dtype dtype('|S5')

La media de la matriz se puede calcular usando el método de la media, de la siguiente manera.

>>> importar numpy como np


>>> x = np.array([1,5,9.0,15]) >>> x.sum()
30.0

¿Notaste la diferencia entre llamar atributos y métodos? Los métodos realizan alguna acción en el objeto y, a
menudo, la acción necesita alguna entrada, por lo que los métodos se llaman con corchetes (). Si hay alguna
entrada para dar al método, se puede dar entre paréntesis, si no hay entrada, se usan corchetes vacíos. Intente
usar los métodos (por ejemplo, sum) sin dar el paréntesis, verá solo algunos detalles al respecto y ningún resultado.

Como Python es un lenguaje de programación orientado a objetos (OOP), los atributos y métodos se usan con
bastante frecuencia. Es mejor saber brevemente sobre ellos antes de saltar a Python. Los atributos representan
propiedades de un objeto y pueden ser de cualquier tipo, incluso del tipo del objeto que lo contiene. Los métodos
representan lo que un objeto puede hacer. Un atributo solo puede tener un valor o un estado, mientras que un
método puede hacer algo o realizar una acción.

2.4 Elegir el nombre de la variable


Luego, el nombre de las variables debe ser significativo y, posiblemente, debe documentarse para qué se usa la
variable.

Los nombres de las variables pueden ser arbitrariamente largos. Pueden contener letras y números, pero deben
comenzar con una letra. Es legal usar letras mayúsculas, pero es una buena idea comenzar los nombres de
variables con una letra minúscula, ya que convencionalmente se usan letras mayúsculas para indicar clases.
Machine Translated by Google

2.5. Operadores y operandos 13

El carácter de subrayado (_) puede aparecer en un nombre. A menudo se usa en nombres con varias palabras,
como my_name o airspeed_of_unladen_swallow. Un nombre de variable puede comenzar con un guión bajo, pero
debe evitarse porque esto se usa convencionalmente para otra cosa.

Python tiene algunas de las palabras clave reservadas, que no se pueden usar como nombre de variable. Si el
intérprete da algún error sobre uno de sus nombres de variables y no sabe por qué, debe verificar si su nombre de
variable no está en la lista de palabras clave reservadas. Es una buena idea recordar la lista o tenerla a mano. Pero
yo, siendo una persona perezosa, no recuerdo esta lista, y de hecho ni siquiera intenté recordarla. Simplemente
escribo el nombre de la variable que quiero usar en python, y busco el resultado de python, y luego decido si usar
este nombre para la variable o no.

>>> 500_mangos
Archivo "<stdin>", línea 1
500_mangos
ˆ

Error de sintaxis: sintaxis invalida


>>> clase
Archivo "<stdin>", línea 1
clase
ˆ

Error de sintaxis: sintaxis invalida


>>> np
<módulo 'numpy' de '/usr/lib/pymodules/python2.7/numpy/__init__.pyc'> >>> foo

Rastreo (llamadas recientes más última):


Archivo "<stdin>", línea 1, en <módulo>
NameError: el nombre 'foo' no está definido

El primer nombre de variable 500_mangoes da SyntaxError, por lo que no podemos usar este nombre como
variable. La clase también proporciona SyntaxError, por lo que tampoco se puede usar. El np da alguna salida (lo
que significa que np se refiere a algo), así que si usamos esto como nombre de variable, la referencia se destruirá.
El foo le da a NameError que la variable no está definida, esto lo convierte en una opción válida para el nombre de
la variable. Aparte de estos escenarios, es posible una salida más.

>>> un = 5
>>> un
5

Esto significa que la variable a está definida antes, ahora depende de usted si desea cambiar su valor anterior.

2.5 Operadores y operandos

Los operadores son símbolos especiales que representan cálculos como la suma y la multiplicación. Los valores a
los que se aplica el operador se denominan operandos. Suponga que la variable a tiene 2 y la variable b tiene 5.
Machine Translated by Google

14 Capítulo 2. Un poco de Python

Nombre del operador Ejemplo


+ Más >>> a+b
7
- Menos >>> ab
-3
* >>> a*b
Multiplicar
10
/ Dividir >>> a/b
0 (para Python 2.x)
0.4 (para Python 3.x)
** Energía >>> a**b
32
% Módulo >>> b\%a
1
== Igual a >>> a==b
Falso
< Menos que >>>a<b
Verdadero

> Mas grande que >>>a>b


Falso
<= Menos que o igual a >>>a<=b
Verdadero

>= Mayor qué o igual a >>>a>=b


Falso
!= No igual a >>>a!=b
Verdadero

y Y >>> Verdadero y Falso


Falso
o O >>> Verdadero o Falso
Verdadero

no No >>> no es cierto
Falso
+= Añadir Y asignación >>> un += segundo

7
ÿ=
Restar Y asignar >>> un -= segundo

3
ÿ=
Multiplica Y asigna >>> un *= segundo

10
/= Dividir Y asignar >>> un /= segundo
0
%= Módulo Y asignación >>> un %= segundo

2
ÿÿ =
Exponente Y asignación >>> un **= segundo
32
// = División de piso Y asignación >>> a //= b
0
Machine Translated by Google

2.6. Expresiones 15

2.6 Expresiones

Una expresión es una combinación de valores, variables y operadores. Un valor en sí mismo se considera una
expresión, al igual que una variable, por lo que las siguientes son todas expresiones legales (suponiendo que a
la variable x se le haya asignado un valor):

>>> x = 17
>>>x + 15
32

Si escribe una expresión en modo interactivo, el intérprete la evalúa y muestra el resultado:

>>> 1 + 1
2

¡Pero en un guión, una expresión por sí sola no hace nada! Esta es una fuente común de confusión para los
principiantes.

2.7 Flujo de control

Si queremos hacer la misma tarea muchas veces, restrinja la ejecución de la tarea solo cuando se cumpla alguna
condición, el flujo de control es la forma de hacerlo.

2.7.1 para

for se utiliza para ejecutar repetidamente algún código. También se puede usar para iterar sobre alguna lista.
Suponga que tiene una lista y desea cuadrar cada elemento de la lista e imprimir.

>>> foo = [5, 11, 14, 0, 6, 0, 8] # define la lista >>> para el elemento en
foo:
... elemento de impresión**2
...
25
121
196
0
36
0
64

El elemento de la lista se puede iterar definiendo otra lista que tenga enteros e iterando sobre ella. Intentemos
de esta manera realizar la tarea anterior.

>>> foo = [5, 11, 14, 0, 6, 0, 8] # define la lista >>> a = range(7) # define
la lista que tiene enteros
>>> un
[0, 1, 2, 3, 4, 5, 6] >>> para
elemento en a:
... imprimir foo[elemento]**2
...
Machine Translated by Google

dieciséis
Capítulo 2. Un poco de Python

25
121
196
0
36
0
64

2.7.2 mientras

while se usa la declaración, cuando queremos seguir ejecutando algún código a menos que se cumpla o se viole
alguna condición. Supongamos que queremos imprimir algunos números que van del 15 al 20, podríamos hacer
esto.

>>> n = 15 # inicializamos la n
>>> mientras que n<=20:
... imprimir
... n = n+1
...
15
dieciséis

17
18
19
20

2.7.3 si

Si la declaración ejecuta una parte del código, si se cumplen las condiciones, de lo contrario, omite esa parte.
Supongamos que tiene una lista y desea calcular su inversa, pero quiere omitir si la entrada en la lista es cero:

>>> foo = [5, 11, 14, 0, 6, 0, 8] # define la matriz >>> para el elemento
en foo:
... si el artículo no es 0:
... imprime 1.0/artículo
...
0.2
0.0909090909091
0.0714285714286
0.166666666667
0.125

El if-else permite que se ejecuten porciones alternativas de código dependiendo de la condición. En if-else
solo se ejecuta una parte del código de las alternativas dadas. Suponga que en el ejemplo anterior desea
emitir alguna declaración cuando hay 0 en la lista.
Machine Translated by Google

2.7. Flujo de control 17

>>> foo = [5, 11, 14, 0, 6, 0, 8] # define la matriz


>>> para el artículo en foo:
... si el artículo no es 0:
... imprimir 1.0/artículo
... más:
... imprimir '0 encontrado en la lista'
...
0.2
0.0909090909091
0.0714285714286
0 encontrado en la lista
0.166666666667
0 encontrado en la lista
0.125

if-elif-else se usa cuando, dependiendo de la condición, desea ejecutar una parte de


código. Puede especificar tantas condiciones como desee y su código correspondiente para ejecutar. Permite
tome un ejemplo, suponga que tenemos una lista y queremos imprimir alguna declaración si el elemento en la lista
es negativo, positivo o 0.

>>> foo = [5, -11, 14, 0, -6, 0, 8] # define la matriz


>>> para el artículo en foo:
... si elemento < 0:
... imprimir 'elemento es negativo'
... elemento elif>0:
... imprimir 'el artículo es positivo'
... más:
... imprimir 'el artículo es 0'
...
el artículo es positivo
el articulo es negativo
el artículo es positivo
el artículo es 0

el articulo es negativo
el artículo es 0

el artículo es positivo

2.7.4 descanso

La sentencia break, sale del bucle. Suponga que desea imprimir todos los elementos de la lista, pero
desea detener el bucle si encuentra 0.

>>> para el artículo en foo:


... si artículo == 0:
... print('cero encontrado en la lista, deteniendo iteraciones')
... descanso

... más:
... imprimir (elemento)
...
5
Machine Translated by Google

18 Capítulo 2. Un poco de Python

-11
14
cero encontrado en la lista, deteniendo iteraciones

La declaración de ruptura se vuelve útil cuando desea que le suceda algo extraño a su programa, y en
esa condición desea detener la ejecución.

2.7.5 continuar

La declaración de continuación brinda la oportunidad de saltar fuera del ciclo actual (iteración) cuando se
cumple alguna condición. Suponga que no desea imprimir elementos de la lista que son negativos.

>>> foo = [5, -11, 14, 0, -6, 0, 8] # define la matriz >>> para el elemento
en foo: if item<0:
...
... Seguir
... elemento de impresión

...
5
14
0
0
8

2.7.6 pase

La instrucción pass no hace nada. Se puede usar cuando se requiere una declaración sintácticamente pero el
programa no requiere ninguna acción.

>>> foo = [5, -11, 14, 0, -6, 0, 8] # define la matriz


>>> para el artículo en foo:
... pasar
...

Esto se usa a menudo, cuando está desarrollando su código y tiene la intención de poner algo más
tarde. Si sale sin pase, Python emitirá el error.

2.8 Función

La función es una secuencia de declaraciones que realiza algún procesamiento. Cuando define una función,
especifica el nombre y la secuencia de instrucciones. Más tarde, puede llamar a la función por su nombre.
Hay muchas funciones integradas en Python, y cada biblioteca proporciona algunas funciones. También
puede especificar sus funciones. Cuando necesita hacer una tarea muchas veces, es mejor definir la
función para hacer esa tarea y luego llamar a la función. La regla general es que, cada vez que sienta
que debe definir una función, defínala.
Machine Translated by Google

2.8. Función 19

2.8.1 Funciones integradas

Python tiene algunas funciones integradas, algunas de las cuales ya hemos usado.

>>> foo = [5, -11, 14, 0, -6, 0, 8] # define el arreglo >>> type(foo) <type 'list'>
>>> len(foo)

>>> max(foo)
14

Aquí, type, len, max son funciones integradas, que devuelven el tipo, la longitud de la lista y el valor máximo en la
lista, respectivamente.

2.8.2 Funciones definidas por el usuario

Si no encuentra la función que desea utilizar, puede definir una. De hecho, es una buena práctica definir funciones
cada vez que se necesitan, ya que aumenta la legibilidad de los códigos. Una definición de función especifica el
nombre de una nueva función y la secuencia de instrucciones que se ejecutan cuando se llama a la función.

Suponga que desea definir una función que agregue el 2 a la entrada.

>>> def suma2(temp):


... regresa temp+2
...
>>> sumar2(5)
7

>>> foo = np.array( [5, -11, 14, 0, -6, 0, 8]) # define la matriz >>> new_foo = add2(foo) >>> print
new_foo array([ 7, -9, 16, 2, -4, 2, 10])

El retorno define la salida de la función. return es opcional, algunas funciones pueden no devolver nada.

>>> foo = [5, -11, 14, 0, -6, 0, 8] # define el arreglo >>> def add2(temp):

... print temp[-1]+2 # agregar 2 solo a la última entrada en la lista


...
>>> add2(foo)
10
>>> nuevo_foo = add2(foo)
10
>>> nuevo_foo

Esto queda claro a partir de este ejemplo que las funciones no necesitan devolver ningún valor. Como en este ejemplo,
la función solo imprime la última entrada de la lista después de agregarle 2 y no devuelve ninguna.
Machine Translated by Google

20 Capítulo 2. Un poco de Python

2.9 Trazado
Hay varias bibliotecas que proporcionan capacidades de trazado en Python. Me gustó la biblioteca
Matplotlb, y está instalada de la siguiente manera.

$ sudo pip instalar matplotlib

Hagamos nuestra primera gráfica que grafica y contra x. La x contiene valores entre 0 y 2ÿ con intervalos
de 50, y y es el seno de x.

>>> # importar los módulos necesarios >>>


importar numpy como np >>> importar
matplotlib.pyplot como plt >>> # generar x en
el rango de 0 a 2 pi con 50 intervalos >>> x = np.linspace( 0,2*np.pi,50) >>> y =
np.sin(x) # calcular el pecado de x >>> plt.plot(x,y) >>> plt.xlabel('x') > >> plt.ylabel('y')
>>> plt.leyenda(['sin(x)']) >>> plt.mostrar()

El plt es el nombre abreviado dado, que se refiere a la biblioteca matplotlib.pyplot. Todas las funciones de
esta biblioteca deben llamarse mediante plt. mientras los usa. El gráfico hace el gráfico de línea continua,
xlabel pone la etiqueta para el eje x e ylabel pone la etiqueta para el eje y. La leyenda muestra la leyenda
en el gráfico. show() muestra el gráfico, el gráfico se puede guardar con savefig y se puede cerrar con
close(). La figura 2.1 muestra la gráfica de y versus x. La función np.linspace se usa para generar un
vector en el rango de 0 a 2ÿ que tiene 50 elementos igualmente espaciados. En el siguiente capítulo se
proporciona más información sobre la generación de este tipo de vectores.

1.0
pecado(x)

0.5

0.0

0.5

1.0
0 1 2 3 4 5 6 7
X

Figura 2.1: La primera gráfica que muestra y = sin(x) versus x.


Machine Translated by Google

Capítulo 3

Formación

3.1 Generación de arreglos secuenciales

A menudo necesitamos vectores cuyos elementos sigan un orden simple, por ejemplo, un vector que contenga
los elementos [10, 11, 12, 13] o [5, 10, 15, 20] o [1.0, 1.2, 1.4, 1.6, 1.8, 2.0 ]. Vemos que en estos vectores, los
elementos siguen un orden simple, por lo que sería mejor si hubiera una manera fácil de definir este tipo de
vectores. Algunas de las formas de crear estos vectores son las siguientes:

3.1.1 espacio lineal

Si estamos interesados en generar el vector, cuyos elementos están uniformemente espaciados y conocemos
el límite superior e inferior y el número de elementos, entonces, en ese caso, linspace es la opción preferida.

>>> import numpy as np >>>


np.linspace( 0, 2, 9 ) array([ 0. ,
0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])

Debido a que linspace se encuentra en la biblioteca numpy, primero hemos importado la biblioteca y le hemos
dado un nombre abreviado. Luego llamamos al linspace con límite inferior, límite superior y el número de
elementos a generar. En este ejemplo, 0 es el límite inferior, 2 es el límite superior y el número de elementos
es 9. Generemos un vector más para entender más sobre esta función, esta vez tomamos el límite inferior
como 0, el límite superior como 2ÿ, y el número de elementos sea 100.

>>> x = np.linspace( 0, 2*pi, 100 )

Por defecto, el número de elementos es 50, por lo que si no especificamos el número de elementos, obtenemos 50
elementos con el mismo espaciado. Podemos usar la función len para obtener la longitud de cualquier matriz.

>>> foo = np.linspace(0,1) >>>


len(foo)
50
Machine Translated by Google

22 Capítulo 3. Matriz

3.1.2 anaranjado

Supongamos nuevamente que queremos generar un vector cuyos elementos estén uniformemente espaciados,
pero esta vez no conocemos el número de elementos, solo conocemos el incremento entre elementos. En tal
situación se utiliza una gama. arange también requiere límites inferior y superior. En el siguiente ejemplo,
estamos generando el vector que tiene el elemento inferior como 10, el elemento superior como 30 y tiene un
incremento de 30. Entonces, desde el conocimiento del espacio lineal, haremos algo como esto.

>>> np.arange( 10, 30, 5 ) array([10,


15, 20, 25])

¡Vaya! ¿Qué sucedió? ¿Por qué Python no imprimió 30? Porque una función de rango no incluye un segundo
argumento en los elementos. Así que queremos imprimir hasta 30, lo haríamos.

>>> np.arange( 10, 31, 5 ) array([10,


15, 20, 25, 30])

Esta vez obtenemos la salida requerida. El rango también puede tomar un incremento flotante. Generemos un
vector con límite inferior de 0, límite superior de 2 y con un incremento de 0,3.

>>> np.arange( 0, 2, 0.3 ) array([ 0. # acepta argumentos flotantes


, 0,3, 0,6, 0,9, 1,2, 1,5, 1,8])

En el caso del incremento flotante también, el valor máximo de los elementos generados es menor que el
segundo argumento dado al rango.

3.1.3 ceros

zeros se usa cuando queremos generar todos los elementos en el vector como 0.

>>> foo = np.zeros(5) >>>


foo array([ 0., 0., 0., 0., 0.])

3.1.4 unos

ones se usa cuando todos los elementos requeridos en el vector son 1. Digamos que queremos generar una
variable foo que tenga todos los elementos iguales a uno y tenga la dimensión de 3×2.

>>> foo = np.unos((3,2)) >>> foo

matriz ([[ 1., 1.], [ 1., 1.],


[ 1., 1.]])

Recuerde que si el número de dimensiones es más de uno, la dimensión se da como tupla, por ejemplo (2,5).
Machine Translated by Google

3.2. Atributos y métodos útiles 23

3.1.5 vacío
vacío es útil para inicializar las variables. Esto asigna los valores basura a los elementos, que se modificarán más
adelante.

>>> foo = np.vacío((2,5)) >>> foo


array([[ 6.94573181e-310,
2.76947193e-316, 2.74957018e-316,
0.00000000e+000, 0.00000000e+000],
[ 0.00000000e+000, 0.00000000e+000, 6.94573152e-310,
6.34874355e-321, 0.00000000e+000]])

Además, en ceros, unos, vacíos, también se puede definir el tipo de datos (p. ej., int, float, etc.).

>>> foo = np.vacío((2,5),int)


>>> fu
matriz ([[ 140583176970856, 56931856, 59487840,
-3617040655747907584, [ 0, 0],
1285, 0, 140583171090560,
0]])

Puede ver que todos los elementos de foo ahora son enteros, aunque los valores son inútiles.

3.1.6 rand
rand se utiliza para generar variables aleatorias distribuidas uniformemente en el rango de 0 a 1.

>>> foo = np.aleatorio.rand(3,2)


>>> fu
matriz ([[ 0.75644359, 0.07754619], [ 0.50267515,
0.91460249], [ 0.85992345, 0.58662329]])

3.1.7 rand
randn se utiliza para generar una variable aleatoria que tiene una distribución normal con una media igual a cero y
una varianza igual a uno.

>>> foo = np.aleatorio.randn(2,4)


>>> fu
matriz ([[-0.66317015, -1.80129451, 0.56398575, -1.11912727],
[ 0.19218091, 0.21957804, -1.10891128, -0.87418933]])

3.2 Atributos y métodos útiles

El ndarray (arreglo generado usando numpy) proporciona atributos para realizar tareas de uso común rápidamente.
Estos atributos se utilizan para obtener rápidamente las propiedades de ndarray. Así que primero generemos
algún vector cuyos elementos sean números aleatorios normalmente distribuidos, y probemos estos atributos. Aquí yo
Machine Translated by Google

24 Capítulo 3. Matriz

Estoy usando una variable aleatoria distribuida normalmente para demostrar, pero estos atributos se pueden usar
con cualquier matriz numpy. Estamos generando un vector bidimensional de tamaño 5×100.

>>> foo = np.aleatorio.randn(5,100)

Verifiquemos el número de dimensiones (no el tamaño o la forma de la matriz). Número de dimensión significa
cuántas dimensiones están asociadas con la matriz. Por ejemplo, en la terminología matemática, el vector tiene una
dimensión, la matriz tiene dos dimensiones.

>>> foo.ndim
2

Se accede a la dimensión de la matriz utilizando el atributo de forma.

>>> foo.forma (5,


100)

El atributo de tamaño proporciona el número total de elementos en la matriz. Esto es simplemente la multiplicación
de todos los elementos dados por atributos de forma.

>>> foo.tamaño
500

El tipo de datos (es decir, flotante, entero, etc.) se extrae utilizando el atributo dtype.

>>> foo.dtype
dtype('float64')

Esto nos dice que la variable foo es flotante y tiene 64 bits. El promedio o la media de la variable se calcula utilizando
el método de la media.

>>> foo.mean()
-0.11128938014455608

Esto proporciona la media de toda la matriz (es decir, 500 elementos en este caso). Supongamos que queremos estimar
la media en alguna dimensión, digamos la segunda (1) dimensión, entonces en este caso necesitamos proporcionar un
parámetro adicional a la media, es decir, el eje.

>>> foo.media(eje=1)
array([-0.07311407, 0.0705939 , -0.09218394, 0.0775191 , 0.01026461])

El mínimo, el máximo, la desviación estándar y la varianza de la matriz se estiman mediante los métodos min, max,
std y var.

>>> # para obtener el valor mínimo >>>


foo.min() -3.5160295160193256 >>> #
para obtener el valor máximo >>> foo.max()

3.0989215376354817
Machine Translated by Google

3.3. Indexación 25

>>> # para obtener la desviación estándar >>>


foo.std()
0.9528004743319175
>>> # para obtener la varianza >>>
foo.var()
0.90782874388712709

Recuerda que la línea que comienza con # representa los comentarios. Los comentarios facilitan la lectura y
comprensión del código. Así que pon comentarios cada vez que hagas algo, lo cual no es fácil de interpretar desde
el código.

La traza de la matriz representa la suma de los elementos de la diagonal, y tiene significado en caso de matriz
cuadrada. Python incluso permite estimar la traza incluso cuando la matriz no es cuadrada, y la traza se calcula
usando los atributos de la traza.

>>> foo.traza()
1.081773080044246

Hay una cantidad de atributos asociados con cada clase, la función dir es una herramienta útil para explorar los
atributos y métodos asociados con cualquier variable, clase, biblioteca, etc. Veamos qué métodos y atributos tienen
nuestra variable foo.

>>> # para obtener la lista de todos los atributos asociados con la variable foo >>> dir(foo)

['T', '__abs__', ............. 'plano', 'vista']

La salida de dir(foo) es muy larga y se omite por brevedad. Se supone que los atributos/métodos que comienzan
_ con son los atributos privados y, a menudo, no son necesarios.

3.3 Indexación
En esta sección, discutiremos cómo hacer referencia a algunos elementos en la matriz numpy. Recuerde que en
Python los primeros índices son 0. Generaremos una matriz, digamos una matriz cuyos elementos se potencian a
3 de la secuencia [0,1, ..., 9].

>>> foo = np.arange(10)**3 >>> foo


array([ 0,
1, 8, 27, 64, 125, 216, 343, 512, 729])

Imprime el tercer elemento de la matriz. El tercer elemento significa que necesitamos poner índices como 2.

>>> foo[2]
8

Supongamos que nos gustaría imprimir alguna secuencia de matriz, digamos en índices de 2,3 y 4.

>>> foo[2:5]
array([ 8, 27, 64])
Machine Translated by Google

26 Capítulo 3. Matriz

Usamos 2:5 para obtener los valores en los índices de 2, 3 y 4. Esto es lo mismo que decir que
foo[np.arange(2,5,1)]. Cuando no especificamos el tercer valor en los índices de matriz, es
por defecto se toma como 1. Si queremos imprimir valor en 2 a 8, con un intervalo de 3. Ahora porque el
intervalo no es 1, por lo que necesitamos definirlo.

>>> fuu[2:10:3]
matriz ([ 8, 125, 512])

Si dejamos la primera entrada en el índice en blanco, es decir, para obtener elementos de matriz desde el comienzo de la matriz
con un intervalo de 2 y hasta 6, emitimos el siguiente comando:

>>> foo[:6:2] # da el elemento en 0,2,4


array([ 0, 8, 64])

Obtenemos elementos hasta los índices de 4, porque un rango no llega hasta el segundo argumento. Nosotros
puede usar índices también para modificar los elementos existentes en la matriz, de la misma manera que accedimos
a ellos. Reemplacemos el valor existente de los elementos en los índices 0,2 y 4, por -1000.

>>> foo[:6:2] = -1000 # modificar los elementos en 0,2,4


>>> fu
matriz([-1000, 1, -1000, 27, -1000, 125, 216, 343, 512, 729])

Obtenemos los últimos elementos de una matriz por índices -1. También podemos usar esto para invertir la matriz, por
dando el incremento de -1.

>>> foo[::-1] # invertido un


array([ 729, 512, 343, 216, 125, -1000, 27, -1000, 1, -1000])

Podemos realizar el cálculo en toda la matriz numpy a la vez. Supongamos que estamos interesados en estimar la
raíz cuadrada de la matriz numpy, podemos usar la función sqrt de la biblioteca numpy.

>>> np.sqrt(foo) # calcular la raíz cuadrada


formación([ yaya, 1. , abuela, 5.19615242,
abuela, 11.18033989, 14.69693846, 18.52025918,
22.627417 , 27 ])
Advertencia: valor no válido encontrado en sqrt

nan representa que el elemento es 'No es un número'. Entonces, cuando el valor del elemento es negativo, el
la salida de sqrt se convierte en nan. La advertencia emitida por Python dice que había algunos valores no válidos
en la entrada para la que sqrt no puede producir ningún resultado sensible, y proporciona una advertencia (no errores).
En realidad, la raíz cuadrada de un número negativo es un número complejo, pero debido a que no definimos el
variable como compleja, numpy no puede realizar operaciones de números complejos en esto. Nosotros necesitamos
biblioteca que maneja números complejos para tal situación.

3.4 Manipulación de matriz


A menudo necesitamos cambiar la matriz, transponerla, obtener algunos elementos o cambiar algunos elementos. Este
se ilustra con este ejemplo, en el que primero creamos la matriz y luego jugamos con ella. Tenemos
ya visto en el apartado anterior, que podemos cambiar el valor de cualquier elemento llamándolo por el
Machine Translated by Google

3.4. Manipulación de matrices 27

índices, y luego asignarle un nuevo valor. Primero, generamos un número aleatorio normalmente distribuido
de tamaño (2 × 5) para crear una matriz, que nos gustaría manipular.

>>> foo = np.aleatorio.randn(2,3) >>> foo

matriz([[ 1.02063865, 1.52885147, 0.45588211],


[-0.82198131, 0.20995583, 0.31997462]])

La matriz se transpone utilizando atributos T.

>>> matriz
foo.T([[ 1.02063865, -0.82198131], [ 1.52885147,
0.20995583], [ 0.45588211,
0.31997462]])

Podemos acceder a algunos elementos del array, y si queremos, también se les pueden asignar nuevos valores.
En este ejemplo, primero accederemos al elemento en los índices (0,1), y luego lo reemplazaremos por 5.
Finalmente, imprimiremos la variable para verificar si la variable se modificó.

>>> foo[0,1]
-0.82198131397870833
>>> foo[0,1]=5
>>> fu
matriz ([[ 1.02063865, 5. ],
[ 1.52885147, 0.20995583],
[ 0.45588211, 0.31997462]])

La forma de cualquier matriz se cambia mediante el método de remodelación. Durante la operación de reforma,
no se permite el cambio en el número de elementos. En el siguiente ejemplo, primero crearemos una matriz
con un tamaño de (3×6), y luego cambiaremos su forma a (2×9).

>>> foo = np.random.randn(3,6)


array([[ 2.01139326, 1.33267072, 1.2947112 , 0.07492725, 0.49765694,
0.01757505],
[0,42309629, 0,95921276, 0,55840131, -1,22253606, -0,91811118,
0.59646987],
[ 0.19714104, -1.59446001, 1.43990671, -0.98266887, -0.42292461, -1.2378431 ]]) >>>
foo.reshape(2,9) array([[ 2.01139326, 1.33267072, 1.2947112 0.01757505, 0.42309629,
0.95921276, 0.55840131],
, 0.07492725, 0.49765694,

[-1.22253606, -0.91811118, 0.59646987, 0.19714104, -1.59446001,


1.43990671, -0.98266887, -0.42292461, -1.2378431 ]])

Al igual que podemos acceder a cualquier elemento de la matriz y cambiarlo, de manera similar podemos
acceder a cualquier atributo y modificarlo. Sin embargo, la modificación solo se permite si los atributos se
pueden escribir y el nuevo valor tiene algún sentido para la variable. Podemos usar este comportamiento y
cambiar la forma de la variable usando los atributos de forma.

>>> foo = np.aleatorio.randn(4,3)


Machine Translated by Google

28 Capítulo 3. Matriz

>>> foo.forma (4,


3) >>> foo

Array ([[ -1.47446507, -0.46316836, 0.44047531], [-0.21275495,


-1.16089705, -1.143494478], [-0.83299338, 0.203336677,
0.13460515], [-1.73204204204204204204

>>> foo.forma = 2,6 >>>


foo.forma (2, 6)

>>> fu
matriz([[-1.47446507, -0.46316836, 0.44047531, -0.21275495, -1.16089705, -1.14349478], [-0.83299338,
0.20336677, 0.13460515, -1.733043066,0

1.13514327]])

En el ejemplo anterior, primero se define una matriz con un tamaño de (4×3) y luego a su forma se le asigna
un valor de (2,6), lo que hace que la matriz tenga un tamaño (2×6). Como no podemos cambiar el número de
elementos, si definimos una dimensión de la nueva variable, la segunda dimensión se puede calcular con facilidad.
Numpy nos permite definir -1 para la dimensión predeterminada en este caso. Podemos hacer el cambio deseado en la
forma de la variable utilizando también la dimensión predeterminada.

>>> foo.forma = -1,6 >>>


foo.forma (2, 6)

Podemos aplanar la matriz (hacer que la matriz sea unidimensional) utilizando el método de desmontaje, que se
explica en el siguiente ejemplo:

>>> foo = np.aleatorio.rand(2,3)


>>> fu
matriz ([[ 0.82866532, 0.99558838, 0.58213507], [ 0.48877906,
0.67700479, 0.35975352]])
>>> foo.forma (2,
3) >>> a =
foo.ravel() >>> a.forma (6,)

>>> un
matriz([ 0.82866532, 0.99558838, 0.58213507, 0.48877906, 0.67700479,
0.35975352])
Machine Translated by Google

Capítulo 4

Aplicaciones básicas en Hidrología

4.1 Introducción
Este capítulo proporcionará aplicaciones de python en hidrología. La mayoría de los problemas
presentados en este capítulo están tomados del libro titulado “Hidrología aplicada” de Chow et al, y para
una descripción detallada de los mismos, debe consultar el libro. Estos ejemplos incluyen las ecuaciones
comúnmente encontradas en la hidrología. Elegí estos problemas para enseñar Python usando ejemplos
y, además, en cada ejemplo aprenderemos cosas nuevas sobre Python.

4.2 Vapor de agua


Aproximadamente, la presión de vapor de saturación (es) está relacionada con la temperatura del aire (T) por la
siguiente ecuación,
17.27T
es = 611 exp , (4.1)
237.3+T

donde, es está en pascales y T está en grados Celcius. Calculemos el valor de es en T = 50.

>>> T = 50
>>> es = 611*np.exp(17.27*T/(237.3+T)) >>>
imprimir(es) 12340.799081

Grafiquemos la variación de es versus T en el rango de ÿ100 ÿ T ÿ 100. El plt.plot(x,y) hace el gráfico


lineal de y versus x, con el color azul predeterminado. Los plt.xlabel() y plt.ylabel()” se utilizan para
escribir etiquetas en los ejes x e y respectivamente. La entrada de xlable e ylabel debe ser una cadena
o una variable que contenga una cadena. El plt.show() muestra el gráfico en la pantalla de la computadora.

>>> import numpy as np >>>


T = np.linspace(-100,100,50) >>> es =
611*np.exp(17.27*T/(237.3+T)) >>> plt.plot(T ,es)
>>> plt.xlabel('T (grados Celcius)')
Machine Translated by Google

30 Capítulo 4. Aplicaciones básicas en Hidrología

>>> plt.ylabel('es (Pa)') >>> plt.mostrar()

El gráfico resultante se muestra en la Fig. 4.1. Este ejemplo demuestra cómo visualizar gráficamente la variación de
una variable con respecto a la otra variable, mientras que la anterior es función explícita de la posterior.

120000

100000

80000

60000

40000

20000

0 100 50 0 50 100
T (grados Celsius)

Figura 4.1: La variación de la presión de vapor de saturación (es) frente a la temperatura (T).

4.3 Precipitación

La velocidad terminal (Vt) de una gota de lluvia que cae está dada por:

1/2
4gD ÿw
Vt = ÿ1 , (4.2)
3CD ÿa

donde g es la aceleración de la gravedad, D es el diámetro de la gota de lluvia que cae, ÿw es la densidad del agua, ÿa
es la densidad del aire y Cd es el coeficiente de arrastre. La ley de Stoke se puede utilizar para calcular el coeficiente
de arrastre (Cd = 24/Re), que es válido para gotas de lluvia con un diámetro inferior a 0,1 mm. Re es el número de
Reynold, que se puede calcular como ÿaV D/µa. Supongamos que el Re se da como 5,0, y la gota de lluvia tiene un
diámetro de 0,05 mm, y queremos estimar el Vt . (ÿw = 998, ÿa = 1,2).

>>> importar numpy como np


>>> Re = 5.0; rho_w = 998; rho_a = 1,2; g = 9,8; D = 0.05E-3 >>> Cd = 24/Re >>> Vt =
np.sqrt((4*g*D)/(3*Cd)*(rho_w/rho_a-1))

>>> VT
0.3362483649967134

En este ejemplo vemos que ';' nos permite definir muchas expresiones en una línea.
Machine Translated by Google

4.4. Lluvia 31

4.4 Precipitaciones

A menudo, se nos da una precipitación registrada por un pluviómetro que proporciona las profundidades de lluvia registradas
para intervalos sucesivos en el tiempo, y queremos calcular la precipitación acumulada. En este ejemplo primero
crearemos lluvia usando los números aleatorios, y también crearemos una variable de tiempo que tenga
valores [0,5,10, ...., 100].

>>> importar numpy como np


>>> tiempo = np.linspace(0,100,21) # crear variable de tiempo
>>> tiempo

matriz ([ 0., 5., 45., 50., 55., 10, 15, 20, 25, 30, 60, 65, 70, 75, 35., 40.,
90., 95., 100.]) 80., 85.,

>>> lluvia = np.random.rand(21) # generar lluvia


>>> lluvia
matriz([ 0.08155645, 0.88821997, 0.33355457, 0.49600859, 0.6315054 0.0722053 , 0.06165701, ,
0.96105307, 0.56483934, 0.5194715 ,
0.35780167, 0.98950575, 0.67866578, 0.31274527, 0.80022389,
0.53321842, 0.82370443, 0.73212013, 0.77039599, 0.06392391,
0.53481488])

Ahora hacemos un gráfico de barras usando plt.bar(), para la lluvia que representa el comportamiento temporal de
la lluvia

>>> importar matplotlib.pyplot como plt


>>> plt.bar(tiempo,lluvia)
>>> plt.xlabel('Tiempo')
>>> plt.ylabel('Lluvia incremental')
>>> plt.savefig('/home/tomer/articles/python/tex/images/rain.png')

El gráfico de barras resultante de la precipitación se muestra en la Fig. 4.2. Es posible que haya notado que en la sección 4.2,
usamos plt.show(), mientras que en el ejemplo anterior usamos plt.savefig. El plt.mostrar()
muestra el gráfico en la pantalla de la computadora, que se puede guardar más tarde, mientras que plt.savefig() guarda el
gráficos en la computadora, que se pueden ver después de abrir el archivo. Es solo cuestión de gustos, lo que Ud.
como, opcionalmente, ambos se pueden hacer en el mismo gráfico. Prefiero guardar las cifras en la computadora y
entonces verlos.

La suma acumulativa se calcula utilizando la función cumsum de la biblioteca numpy.

>>> cum_rainfall = np.cumsum(lluvia)

Ahora graficamos la precipitación acumulada. La precipitación acumulada resultante se muestra en la Fig. 4.3. los
plt.clf() borra la figura actual, y es muy útil cuando se hacen parcelas múltiples, y hay
cualquier parcela existente en la memoria de python. Simplemente no use el clf en esto, y vea la diferencia.

>>> plt.clf()
>>> plt.plot(tiempo,cum_rainfall)
>>> plt.xlabel('Tiempo')
>>> plt.ylabel('Lluvia acumulada')
>>> plt.savefig('/home/tomer/articles/python/tex/images/cum_rain.png')
Machine Translated by Google

32 Capítulo 4. Aplicaciones básicas en Hidrología

Figura 4.2: Variación temporal de la lluvia incremental.

Figura 4.3: Comportamiento temporal de la precipitación acumulada .

Por lo general, nos dan la precipitación en algunos pluviómetros, y queremos hacer el gráfico de isoyeta (contorno)
de la precipitación. Para demostrar esta situación, primero generaremos ubicaciones (x,y) y lluvia para diez
estaciones utilizando números aleatorios. Las ubicaciones generadas de los pluviómetros se muestran en la Fig. 4.4.

>>> # importar módulos requeridos >>>


importar numpy como np >>> importar
matplotlib.pyplot como plt
>>>
>>> #generar ubicaciones y precipitaciones >>> x
= np.random.rand(10) >>> y = np.random.rand(10)
>>> lluvia = 10*np.random.rand(10)

>>>
>>> #traza las ubicaciones >>>
plt.scatter(x,y) >>> plt.xlabel('X')
>>> plt.ylabel('Y') >>> plt.savefig('/
home /tomer/articles/python/tex/
images/loc.png')
Machine Translated by Google

4.4. Lluvia 33

Prefiero agregar líneas en blanco después de una sección de código y comentar en la parte superior de la sección lo que está haciendo.
Esto aumenta la legibilidad del código. El plt.scatter() hace el gráfico de dispersión, es decir, los puntos se trazan
en lugar de las líneas. Cuando no hay orden en los datos con respecto a su posición en la matriz, se usa el
diagrama de dispersión. Como en este caso, es posible que haya dos estaciones que estén cerca, pero que estén
ubicadas a distancia en la matriz.

Figura 4.4: Distribución espacial de los pluviómetros.

El diagrama de flujo de la preparación del mapa de contorno se muestra en la Fig. 4.5. Primero, necesitamos
generar la grilla con espaciado regular que tenga la misma extensión que las ubicaciones de los pluviómetros.
Luego, a partir de la ubicación dada y los datos de lluvia, necesitamos calcular los datos en una cuadrícula regular
usando algún esquema de interpolación. Después de esto, se pueden obtener mapas de contorno. La función
griddata de la biblioteca scipy.interpolate es útil para obtener los datos cuadriculados (datos en una cuadrícula
regular). Cuando necesitamos solo una o pocas funciones de la biblioteca, es mejor llamarlas explícitamente, por
ejemplo, desde scipy.interpolate import griddata, como en el siguiente ejemplo. Usamos la función meshgrid de la
biblioteca numpy para crear la malla a partir de los vectores x e y dados.

>>> from scipy.interpolate import griddata >>> #generar la


cuadrícula deseada, donde se interpolará la lluvia >>> X,Y = np.meshgrid(np.linspace(0,1,1000),
np.linspace( 0,1,1000))
>>>
>>> #realiza la cuadrícula >>>
grid_rain = griddata((x,y), lluvia, (X, Y))

Ahora, podemos hacer el gráfico de contorno de los datos cuadriculados, que se hace con la función plt.contourf().
El contorno hace contornos rellenos, mientras que el contorno () proporciona un contorno simple. Intente usar el
contorno en lugar de contornof, y verá la diferencia. Comenzamos por borrar la figura actual usando plt.clf(), ya
que puede haber alguna figura existente en la memoria, especialmente si está siguiendo todos los ejemplos en la
misma sesión. También superponemos las ubicaciones de los pluviómetros con plt.scatter(). La syc se utilizan
para definir el tamaño y el color de los marcadores respectivamente. plt.xlim() y plt.ylim() limitan la extensión de
los ejes x e y respectivamente.

>>> plt.clf() >>>


plt.contourf(X,Y,grid_rain) >>> plt.colorbar()
>>> plt.xlabel('X') >>> plt.ylabel('Y' )
Machine Translated by Google

34 Capítulo 4. Aplicaciones básicas en Hidrología

Ubicación de los medidores Datos (por ejemplo, lluvia)

Cuadrícula
regular con la Interpolar
extensión y el espaciado requeridos

Datos cuadriculados

Mapa de contorno

Figura 4.5: Diagrama de flujo para hacer un mapa de contorno a partir de los datos de los pluviómetros

>>> plt.dispersión(x, y, s=30, c='r') >>> plt.xlim((0,1)) >>>


plt.ylim((0,1)) >>> plt.savefig('/home/tomer/articles/python/
tex/images/grid_rain.png')

La Fig. 4.6 muestra la precipitación cuadriculada junto con la ubicación de los pluviómetros. Gridata no realiza extrapolaciones, por lo
que a los datos fuera de la ubicación de los pluviómetros se les asigna un valor de nan.
Hay otras funciones que se pueden usar para extrapolar los datos, que se discutirán más adelante.

Figura 4.6: Precipitación cuadriculada junto con la ubicación de los pluviómetros.

4.5 Evaporación
Con base en el balance de energía, la tasa de evaporación (Er) después de despreciar el flujo de calor sensible y el flujo de calor del
suelo, se puede calcular como,
Rn
Er = , (4.3)
lvÿw
Machine Translated by Google

4.5. Evaporación 35

donde, Rn es la radiación neta, lv es el calor latente de vaporización y ÿw es la densidad del agua. El lv se puede
aproximar como,
lv = 2500ÿ2.36×T, (4.4)

donde, T es la temperatura en Celsius.

Según la aerodinámica, la tasa de evaporación (Ea) se puede calcular como,

Ea = B(eas ÿea), (4.5)

dónde,
0.622k 2ÿau2
B= (4.6)
pÿw [ln(z2/z0)]2 ,

eas es la presión de vapor saturado, ea es la presión de vapor, k es el coeficiente de von Karnman, u2 es la


velocidad del viento medida a una altura de z2 m, p es la presión del aire y z0 es la altura de rugosidad.

Por lo general, la evaporación se calcula combinando el balance de energía y el método aerodinámico. En este
caso la E se convierte en,
ÿ ÿ
mi = Er + Ea, (4.7)
ÿ+ÿ ÿ+ÿ

donde, ÿ es el gradiente de la curva de presión de vapor saturado, y es,

4098es
ÿ = (273,3+T) 2, (4.8)

y, la ÿ es la constante psicrométrica, y se define como,

CpKh
pÿ = 0.622lvKw , (4.9)

kh y kw son las difusividades de calor y vapor respectivamente.

Primero generemos los datos sintéticos usando números aleatorios. Sabemos que np.random.rand proporciona
un número aleatorio uniformemente distribuido en un intervalo de [0,1]. Si queremos obtener el número aleatorio
uniformemente distribuido en algún otro rango, digamos [a,b], podemos transformar la variable de la siguiente
manera:
xnuevo = a+ (bÿa) ÿ xviejo, (4.10)

donde, Xold es una variable aleatoria uniformemente distribuida sobre [0,1], y xnew tiene el rango de [a,b].
El np.random.randn da variables aleatorias normalmente distribuidas que tienen media cero y desviación
estándar igual a uno. Si estamos interesados en una variable aleatoria distribuida normalmente que tiene media
µ y desviación estándar igual a ÿ. Podemos hacer la siguiente transformación.

ynuevo = µ+ÿÿ yviejo, (4.11)

donde, ynew es una variable transformada que tiene una media igual a µ y una desviación estándar igual a ÿ, y
yold es la variable aleatoria normalmente distribuida con una ecuación de media cero y desviación estándar igual
a uno, generada por la función np.random.randn.

En el siguiente ejemplo, generaremos variables en su rango habitual. El comentario después de la


Machine Translated by Google

36 Capítulo 4. Aplicaciones básicas en Hidrología

variable proporciona detalles del rango inferior y superior en el caso de una variable aleatoria distribuida
uniformemente, media y desviación estándar cuando la variable tiene una distribución normal.

>>> de la división de importación __future__ >>>


importar numpy como np >>> importar
matplotlib.pyplot como plt
>>>
>>> # generar los datos sintéticos >>> Rn =
150+100*np.random.rand(100) # límite inferior = 150, límite superior = 250 >>> T = 25+3*np.random.randn( 100)
# media = 25, std = 3 >>> Rh = 0.2+0.6*np.random.rand(100) # límite inferior = 0.2, límite superior = 0.8 >>>
u2 = 3+np.random.randn( 100) # media = 3, estándar = 1

>>>
>>> # define constantes >>>
rho_w = 997; rho_a = 1,19; p = 101,1e3; z2 = 2 >>> z0 = 0.03e-2; k = 0,4;
Cp = 1005

Ahora, aplicamos el método basado en el balance de energía para estimar la evaporación.

>>> lv = (2500-2.36*T)*1000 # multiplicado por mil para convertir de KJ/kg a J/kg >>> Er = 200/(lv*997)

>>> Er *= 1000*86400 # convertir de m/s a mm/día

Estamos usando operadores de multiplicación y asignación para convertir las unidades. Podríamos haber hecho esto
simplemente multiplicando también, es decir, Er = Er*1000*86400. El operador de multiplicación y asignación es
rápido, ya que no crea ninguna variable temporal en la memoria. De hecho, todos los operadores de asignación son
más rápidos que los operadores simples y deben usarse siempre que haya posibilidades de usarlos. Ahora estimamos
la evaporación usando el método aerodinámico.

>>> B = 0.622*k**2*rho_a*u2/(p*rho_w*(np.log(z2/z0))**2) >>> e_s =


611*np.exp(17.27*T/ (237.3+T)) >>> e_a = Rh*e_s >>> Ea = B*(e_s-e_a)

>>> Ea *= 1000*86400 # convertir de m/s a mm/día

Ahora, combinamos el balance de energía y el método aerodinámico para obtener una mejor estimación de la ración de
evaporación.

>>> gamma = Cp*p/(0.622*lv) # ya que kh/kw = 1, por lo que se eliminan de la ecuación. >>> delta = 4098*e_s/
(237.3+T)**2 >>> w = delta/(delta+gamma)

>>> E = w*Er + (1-w)*Ea

Ahora, tenemos cuatro variables importantes; evaporación mediante el método de balance de energía (Er),
evaporación mediante el método de aerodinámica (Ea), evaporación combinada (E) y la relación de evaporación
mediante el método de balance de energía mediante el método combinado (Er/E). Podemos graficar estas cuatro
variables en cuatro gráficos diferentes, o podemos ponerlas en una figura haciendo que la figura se divida en cuatro
secciones. subplot es una función de este tipo para convertir la figura en una subsección. El primer argumento para
la subparcela es el número deseado de filas, el segundo argumento es el número deseado de columnas en la figura.
El tercer argumento es la posición de la subparcela en la figura, que se mide de izquierda a derecha y de arriba a abajo.
Machine Translated by Google

4.5. Evaporación 37

>>> plt.clf() >>>


plt.subplot(2,2,1) >>>
plt.plot(Er) >>>
plt.xlabel('Tiempo') >>>
plt.ylabel('Er ')

>>> plt.subtrama(2,2,2) >>>


plt.trama(Ea) >>>
plt.xlabel('Tiempo') >>>
plt.ylabel('Ea')

>>> plt.subplot(2,2,3, axisbg='y') >>>


plt.plot(E) >>> plt.xlabel('Tiempo') >>>
plt.ylabel('E')

>>> plt.subplot(2,2,4, axisbg='g') >>>


plt.plot(w) >>> plt.xlabel('Tiempo') >>>
plt.ylabel('Er/E ') >>> plt.savefig('/home/tomer/
articles/python/tex/images/E.png')

Los Er , Ea, E y Er/E estimados se muestran en la Fig. 4.7. Además, hemos utilizado el argumento axisbg
para definir el color de fondo de las subparcelas.

Figura 4.7: Er , Ea, E y Er/E estimados.

En la Fig. 4.7, la etiqueta y de la subparcela 4 se superpone con la subparcela 3. Esto se puede corregir
cambiando el wspace. Lo cual se demuestra a continuación. La Fig. 4.8 muestra el gráfico mejorado.

>>> fig = plt.figure() >>>


fig.subplots_adjust(wspace=0.6) >>>
plt.subplot(2,2,1) >>> plt.plot(Er) >>>
plt.xlabel( 'Tiempo') >>> plt.ylabel('Er')
Machine Translated by Google

38 Capítulo 4. Aplicaciones básicas en Hidrología

>>>
>>> plt.subtrama(2,2,2)
>>> plt.plot(Ea)
>>> plt.xlabel('Tiempo')
>>> plt.ylabel('Ea')
>>>
>>> plt.subplot(2,2,3, ejebg='y')
>>> plt.parcela(E)
>>> plt.xlabel('Tiempo')
>>> plt.ylabel('E')
>>>
>>> plt.subplot(2,2,4, ejebg='g')
>>> plt.plot(w)
>>> plt.xlabel('Tiempo')
>>> plt.ylabel('Er/E')
>>> plt.savefig('/home/tomer/articles/python/tex/images/corr_E.png')

Figura 4.8: Er , Ea, E y Er/E estimados con ylabel corregido.

4.6 Infiltración
La infiltración acumulativa dada por el método Green-Ampt se escribe como,

Pie)
F(t)ÿÿÿÿln 1+ = Kt, (4.12)
ÿÿÿ

donde, F(t) es la infiltración acumulada después del tiempo t, ÿ es la cabeza de succión , ÿÿ se da como,

ÿÿ = (1ÿSe)ÿe, (4.13)

donde, Se es el grado de saturación, y ÿe es la porosidad efectiva, K es la conductividad hidráulica. Para


resolver la ecuación usando el procedimiento iterativo, la Ec. 4.12 se reescribe como,

Pie)
F(t) = ÿÿÿln 1+ +Kt. (4.14)
ÿÿÿ
Machine Translated by Google

4.7. Superficie del agua 39

Usamos la función while para iterar hasta lograr la precisión requerida. El valor iterado de F se almacena mediante el
método append. append agrega la matriz por un elemento y coloca la variable de entrada en ella.

>>> de la división de importación __future__ >>>


importar numpy como np

>>> # definir las variables


>>> theta_e = 0,486 >>> psi
= 16,7 >>> K = 0,65

>>> S_e = 0.3 >>>


t=1
>>>
>>> #calcular dtheta >>> dtheta
= (1-S_e)*theta_e
>>>
>>> # estimación inicial de F
>>> F_antiguo = K*t
>>> épsilon = 1
>>> F = [] >>>
mientras épsilon > 1e-4:
>>> F_nuevo = psi*dtheta * np.log(1+F_antiguo/(psi*dtheta)) + K*t epsilon = F_nuevo -
>>> F_antiguo F_antiguo = F_nuevo F.append(F_nuevo)
>>>
>>>

Ahora, hacemos un gráfico del valor iterado de F para ver cómo F se actualiza con las iteraciones. También estamos
usando -ok en la función de trazado. La -o representa la línea continua con puntos rellenos, y la k indica que el color de
la trama es negro. También estamos especificando el tamaño de fuente para xlabel e ylabel.
Hemos usado '25' para ylabel y '20' para xlabel, solo para demostrar que se pueden usar diferentes tamaños de fuente
para diferentes textos. Por supuesto, no es necesario definir un tamaño de fuente diferente para ylabel y xlabel. El mismo
argumento fontsize también se puede usar para definir el tamaño de fuente para la leyenda.

>>> import matplotlib.pyplot as plt >>> plt.plot(F,'-ok')


>>> plt.xlabel('Número de iteración',fontsize=25) >>>
plt.ylabel('F' ,tamaño de fuente=20) >>> plt.savefig('/home/tomer/articles/
python/tex/images/F.png')

La figura 4.9 muestra la variación de F a lo largo del tiempo. La F se vuelve casi constante después de aproximadamente
12 iteraciones.

4.7 Agua superficial

La profundidad de flujo en un canal rectangular está dada por,

5/3 1.49(B+y)
1/2 Q
(Por)
=S
2/3 ,
o (4.15)
norte
Machine Translated by Google

40 Capítulo 4. Aplicaciones básicas en Hidrología

Figura 4.9: La variación de la F con iteraciones.

donde Q es el flujo, n es el coeficiente de Manning, S0 es la pendiente de la superficie del agua, B es el ancho del
canal y y es la profundidad del flujo. Esta es una ecuación no lineal en y, y aún no se encuentra la solución explícita de
esto. Esto se puede resolver iterativamente como en la última sección, o usando métodos como Newton-Raphson. En
esto, resolveremos usando la función fmin de la biblioteca Scipy.optimize.
Primero importaremos las bibliotecas requeridas. Luego definiremos una función que toma la profundidad del flujo (y)
como entrada y da el error en el flujo estimado en base a esta y y la Q dada. Estamos tomando el valor absoluto del
error, otras opciones son como el cuadrado del error, etc. Después de especificar la función, podemos dar esta función
como una entrada a fmin y alguna suposición inicial de la y.

>>> # importar módulos requeridos >>> de


__future__ división de importación >>> importar
numpy como np >>> importar matplotlib.pyplot como
plt >>> de scipy.optimize import fmin

>>>
>>> # define las variables >>> n = 0.015

>>> S0 = 0,025
>>> Q = 9.26
>>> segundo = 2
>>>
>>> # define la función de flujo
>>> def flujo(y):
>>> Q_estimado = (1.49/n)*(S0**0.5)*((B*y)**(5/3))/((B+y)**(2/ 3)) épsilon = np.abs(Q_estimado -
>>> Q) devuelve épsilon
>>>
>>>
>>> y_óptimo = fmin(flujo,0.5)

fmin nos dará el valor y requerido. También podemos obtener detalles de las iteraciones y el valor del error en las
iteraciones finales. Usamos la función de impresión para ver los detalles. La salida se da a continuación.

>>> imprimir(y_óptimo)
La optimización terminó con éxito.
Valor de la función actual: 0.000078
Machine Translated by Google

4.8. Método de enrutamiento fluvial-Muskingum 41

Iteraciones: 13
Evaluaciones de funciones: 26
[ 0.52770386]

La optimización finalizó con éxito, es decir, se logró la precisión requerida dentro del número máximo predeterminado de
iteraciones permitidas. El resultado indica que se necesitaron 13 iteraciones para lograr la precisión requerida y que la
función se evaluó 26 veces en el proceso.

4.8 Enrutamiento fluvial: método Muskingum

El flujo de salida usando el método de Muskingum se calcula como,

Qj+1 = C1Ij+1 +C2Ij +C3Qj . (4.16)

Nos dan el valor de C1, C2, C3 y Q0, y estamos interesados en obtener el valor de Q desde el tiempo (t = 0)
hasta (t = 19). En este ejemplo, primero definimos variables y luego iteramos usando for loop. La lista es bastante
larga y no cabe en una sola línea. En tales casos, también podemos ir a la segunda línea, el comienzo de los
corchetes le dice a Python que la lista ha comenzado, y los corchetes finales le dicen a Python que este es el
final de la lista. Podemos escribir la lista en tantas líneas como queramos, no es necesario especificar nada más
para decirle a Python que la lista está definida en varias líneas.

>>> from __future__ import division >>> import numpy


as np >>> # define las variables >>> I = np.array([93,
137, 208, 320, 442, 546, 630, 678, 691, 675 , 634, 571,
477,
>>> 390, 329, 247, 184, 134, 108, 90])
>>> C1 = 0,0631
>>> C2 = 0,3442
>>> C3 = 0.5927
>>>

>>> Q = np.empty(20) # define el arreglo vacío >>> Q[0] = 85 # valor


inicial de Q
>>>

>>> # iterar sobre >>>


para i en rango(1,20):
>>> Q[i] = C1*I[i] + C2*I[i-1] + C3*Q[i-1]

Ahora podemos usar matplotlib.pyplot para trazar el flujo de entrada y salida. -* significa una línea continua con
comienzos y --s significa una línea discontinua con un cuadrado.

>>> import matplotlib.pyplot as plt >>> plt.plot(I, '-*',


label='Inflow') >>> plt.plot(Q, '--s', label='Outflow') >>>
plt.xlabel('Tiempo', tamaño de fuente=20) >>> plt.ylabel('Flujo',
tamaño de fuente=20) >>> plt.legend() >>> plt.savefig('/home/
tomer /artículos/python/tex/images/muskingum.png')
Machine Translated by Google

42 Capítulo 4. Aplicaciones básicas en Hidrología

Figura 4.10: La variación de entrada y salida con el tiempo.

La Fig. 4.10 muestra la variación del flujo de entrada y salida con el tiempo. El flujo de salida muestra un retraso con respecto al
flujo de entrada, y el pico en el flujo de salida es ligeramente menor que el flujo de entrada.
Machine Translated by Google

Capítulo 5

Estadísticas

Cuando no hay una comprensión clara del proceso físico, o las variables requeridas para hacer un modelo físico
no están disponibles, entonces las estadísticas juegan un papel vital. Hay varios módulos disponibles en python
para manejar estadísticas, el más utilizado es scipy.stats. Además, hay una estadística de módulos más útil, que
se puede descargar desde http://bonsai. hgc.jp/˜mdehoon/software/python/Statistics/manual/index.xhtml. las
estadísticas no están disponibles para descargar usando el pip, y por lo tanto debe descargarlo usando el
navegador de Internet y luego instalarlo usando pip o python setup.py install.

5.1 Distribuciones empíricas


La mayoría de las variables hidrológicas son continuas, pero debido a nuestra capacidad de medición, las
medimos de forma discreta. La clasificación de datos discretos mediante bins proporciona un medio para tratar
los datos discretos como continuos. La visualización de la distribución subyacente de los datos se realiza trazando
el histograma. El histograma representa la frecuencia en intervalos discretos (contenedores). Entonces,
comencemos con el histograma. En el siguiente ejemplo, primero generaremos algunos datos sintéticos y luego
calcularemos y trazaremos el histograma.

>>> de __future__ división de importación >>>


importar numpy como np >>> importar
matplotlib.pyplot como plt >>> importar scipy.stats
como st
>>>
>>> x = np.random.randn(100) # generar algunos datos sintéticos
>>>
>>> # calcular histograma >>> n,
rango_bajo, tamaño de contenedor, puntos extra = st.histograma(x) >>>
rango_superior = rango_bajo+tamaño de contenedor*(len(n)-1) >>> contenedores
= np.linspace(rango_bajo , rango_superior, largo(n))

El st.histogram proporciona el número de contenedores en cada intervalo (n), el rango inferior del contenedor (rango bajo), el ancho de
los contenedores (tamaño del contenedor) y los puntos no utilizados en el cálculo del histograma. Dado que el tamaño del contenedor es
el mismo para todos los contenedores, Python proporciona solo un tamaño de contenedor. Utilizamos el rango inferior del contenedor y
el tamaño del contenedor para calcular primero el rango superior del contenedor y luego calcular el valor medio para todos los contenedores.
Ahora podemos usar la barra para hacer el histograma. También definiremos el ancho y el color de las barras.
Machine Translated by Google

44 Capítulo 5. Estadísticas

>>> plt.bar(bins, n, ancho=0.4, color='rojo') >>> plt.xlabel('X',


tamaño de fuente=20) >>> plt.ylabel('número de puntos de datos
en el bin', tamaño de fuente=15) >>> plt.savefig('/home/tomer/articles/python/tex/images/
hist.png')

El histograma de los datos se muestra en la Fig. 5.1. En este ejemplo, debido a que acabamos de crear 100
números aleatorios a partir de la distribución normal, el histograma no muestra el comportamiento que debería
mostrar la distribución normal.

Figura 5.1: El histograma de x.

Cada barra en el histograma nos dice cuántas veces estuvieron los datos en un contenedor en particular. Una
mejor manera de ver el comportamiento de los datos es mirar el histograma relativo, que nos informa sobre la
probabilidad con la que los datos estaban en algún rango. El histograma relativo o la frecuencia relativa se obtiene
dividiendo la frecuencia de cada intervalo por la suma de las frecuencias de todos los intervalos. El histograma
relativo representa la probabilidad de que se produzcan datos en los contenedores. Podemos usar la función de
histograma para calcular primero el histograma y luego dividirlo por el número total de frecuencias, o podemos usar
directamente la función relfreq. relfreq proporciona la frecuencia relativa, junto con otra salida que es similar a la
del histograma.

>>> relfreqs, lowlim, binsize, extrapoints = st.relfreq(x) >>> plt.bar(bins, relfreqs,


ancho=0.4, color='magenta') >>> plt.xlabel('X', tamaño de fuente =20) >>>
plt.ylabel('Frecuencias relativas', tamaño de fuente=15) >>> plt.savefig('/home/tomer/
articles/python/tex/images/relfreq.png')

Debido a que estamos usando la misma x que se usó en el ejemplo anterior, por lo tanto, no estamos volviendo a
calcular los contenedores. En este diagrama de barras, estamos usando el color magenta. El color diferente de la
trama es solo para que se familiarice con los colores y los tamaños de fuente. Y no significa que debamos usar un
color diferente para el diagrama de frecuencia relativa que el histograma; nada nos impide usar el mismo color.

El histograma relativo se muestra en la Fig. 5.2. El histograma relativo nos dice cómo se comportan los datos
experimentales; cuántas veces (o con qué probabilidad) los datos estaban en algún rango. Los histogramas
relativos solo hablan de datos experimentales, de los datos que tenemos. ¿Qué pasa con los datos que vamos a
obtener en el futuro? El PDF es un mejor indicador para decir algo sobre los datos futuros.
La función de densidad de probabilidad (pdf) de una variable aleatoria es una función que describe la relativa
Machine Translated by Google

5.1. Distribuciones empíricas 45

Figura 5.2: El histograma relativo de x.

probabilidad de que esta variable aleatoria ocurra en un punto dado. La probabilidad de que la variable aleatoria
caiga dentro de una región particular viene dada por la integral de la densidad de esta variable en la región.
La función de densidad de probabilidad no es negativa en todas partes y su integral en todo el espacio es igual
a uno. Podemos dividir la frecuencia relativa por el tamaño del contenedor y obtener el pdf. Una forma sencilla
de calcular pdf es usar la función hist. hist genera el gráfico y también devuelve el valor de pdf sobre cada
contenedor. El número de contenedores se controla dando un segundo argumento, en el siguiente ejemplo se
establece en 10. Los contenedores proporcionan los rangos inferior y superior del contenedor, por lo tanto, su
longitud es uno más que el número de contenedores. Además del color, estamos especificando el valor alfa
para la función hist. el valor alfa controla la transparencia de la trama; 0.0 significa totalmente transparente y 1.0
es totalmente opaco. La Fig. 5.3 muestra el gráfico de barras de la PDF.

>>> n, contenedores, parches = plt.hist(x, 10, normado=1, color de cara='amarillo', alfa=0.5) >>> plt.xlabel('X',
tamaño de fuente=15) >>> plt .ylabel('PDF', tamaño de fuente=15) >>> plt.savefig('/home/tomer/articles/python/
tex/images/pdf.png')

Figura 5.3: El pdf de x.

La función de distribución acumulativa (CDF) describe la probabilidad de que una variable aleatoria X de valor
real con una distribución de probabilidad dada se encuentre en un valor menor o igual que x. cumfreq
Machine Translated by Google

46 Capítulo 5. Estadísticas

proporciona la frecuencia acumulativa de los datos, que se puede utilizar para calcular la CDF. Si dividimos la
frecuencia acumulativa por la frecuencia total, obtenemos la CDF. El último valor de la frecuencia acumulativa
es igual a la frecuencia total, por lo tanto, estamos usando esto para calcular CDF. La CDF se muestra en la
Fig. 5.4.

>>> cumfreqs, lowlim, binsize, extrapoints = st.cumfreq(x) >>> plt.bar(bins[:-1],


cumfreqs/cumfreqs[-1], ancho=0.4, color='negro', alfa =0.45) >>> plt.xlabel('X', tamaño de fuente=15) >>>
plt.ylabel('CDF', tamaño de fuente=15) >>> plt.savefig('/home/tomer/articles/python/ tex/images/cdf.png')

Figura 5.4: La CDF de x.

Podemos usar la función ECDF de la biblioteca scikits para estimar directamente la función de distribución
acumulativa empírica (ECDF). La información sobre scikits se encuentra en http://pypi.python. org/pypi/
scikits.statsmodels. La función de distribución empírica (CDF) es la función de distribución acumulada asociada
con la medida empírica de la muestra. Esta cdf es una función escalonada que salta 1/n en cada uno de los n
puntos de datos. La función de distribución empírica estima la cdf subyacente de los puntos de la muestra. En
el ejemplo anterior, hemos estimado CDF (ECDF) después de clasificar los datos en algunos contenedores.
Esto significa que asumimos que los datos se comportan de manera estadísticamente similar en un rango
pequeño. Podemos estimar CDF sin hacer esta suposición también, lo que se haría usando la función ECDF.
La función ECDF del formulario de salida es un objeto que almacena el valor de los datos y su ECDF
correspondiente. Los datos se recuperan usando ecdf.x y su ECDF correspondiente se recupera usando ecdf.y.
El ecdf es el nombre de la variable que ha definido para almacenar la salida de la función ECDF, si usa algún
otro nombre, necesita usar el mismo nombre para recuperar los atributos x e y.

>>> importar numpy como np


>>> importar scikits.statsmodels.api como sm >>>
importar matplotlib.pyplot como plt
>>>
>>> # generar algunos datos >>>
data = np.random.randn(100)
>>>
>>> # estimar ecdf
>>> ecdf = sm.herramientas.herramientas.ECDF(datos)
Machine Translated by Google

5.1. Distribuciones empíricas 47

Deberíamos graficar ECDF como un diagrama escalonado, porque cada ECDF se encuentra en un pequeño intervalo. El gráfico
ECDF se muestra en la Fig. 5.5.

>>> plt.step(ecdf.x, ecdf.y) >>>


plt.xlabel('datos', tamaño de fuente=20) >>>
plt.ylabel('CDF empírico', tamaño de fuente=15) >>> plt .savefig('/
home/tomer/articles/python/tex/images/ecdf.png')

También podemos usar ecdf para evaluar ECDF en cualquier valor de datos. Evaluemos e imprimamos el valor de
ECDF en algún punto de datos (digamos en 0).

>>> imprimir(ecdf(0))
0.489999999999999999

Figura 5.5: La CDF empírica estimada usando el método ordinario.

La CDF empírica estimada utilizando el método mencionado anteriormente da como resultado la función de paso, que
no se ve tan bien. Una mejor manera de estimar ECDF es usando funciones del núcleo. Esto se puede hacer mediante
el módulo de estadísticas. La biblioteca de estadísticas proporciona funciones para estimar PDF y CDF usando varias
funciones del núcleo. La función cpdf se utiliza para estimar CDF. También hemos definido el nombre de kernal
(Epanechnikov). El kernel disponible se proporciona en el sitio web de la biblioteca. Dentro de la leyenda, estamos
definiendo la ubicación (loc) de la leyenda como la mejor, lo que significa que Python intentará poner la leyenda en el
camino para minimizar la interferencia con la trama. El gráfico resultante después de usar esta curva se muestra en la
Fig. 5.6. Es evidente a partir de esta figura que muestra una variación más suave en comparación con el método
ordinario de estimación del ECDF.

>>> importar estadísticas >>>


y,x = estadísticas.cpdf(data, kernel = 'Epanechnikov') >>> plt.plot(ecdf.x, ecdf.y,
label='Ordinary') >>> plt. plot(x, y, label='Kernel') >>> plt.xlabel('datos', tamaño de
fuente=20) >>> plt.ylabel('CDF empírico', tamaño de fuente=15) >>>
plt.legend( loc='mejor') >>> plt.savefig('/home/tomer/articles/python/tex/images/
kernel.png')
Machine Translated by Google

48 Capítulo 5. Estadísticas

Figura 5.6: Comparación del ECDF estimado por el método ordinario y basado en funciones kernal.

5.2 Distribuciones teóricas


Las distribuciones teóricas se basan en fórmulas matemáticas en lugar de observaciones empíricas.
Existen varios tipos de distribuciones teóricas, las más utilizadas en hidrología son: Normal, Uniforme,
Exponencial, Chi, Cauchy. Los parámetros de las distribuciones se denominan parámetros de ubicación, escala y
forma. El parámetro de ubicación es el que cambia la ubicación del pdf sin afectar otros atributos. El parámetro
de forma es el que cambia la forma de la distribución sin afectar otros atributos. El parámetro que estira o reduce
la distribución se llama parámetros de escala.

Primero generaremos variables aleatorias normalmente distribuidas. La entrada requerida para esto es la ubicación
y el parámetro de escala, que son la media y la desviación estándar en el caso de una distribución normal.
También podemos usar np.random.randn para generar variables aleatorias normalmente distribuidas, pero
scipy.stats proporciona muchas otras utilidades (métodos). Así que usaremos la biblioteca scipy.stats.

>>> importar numpy como np


>>> importar matplotlib.pyplot como plt >>>
importar scipy.stats como st
>>>
>>> # generar instancias de variable aleatoria normalmente distribuida >>> rv1 =
st.norm(loc=0, scale=5) >>> rv2 = st.norm(loc=0, scale=3) >>> rv3 = st.norm(loc=0, escala=7)

Ahora estas instancias de variables se pueden usar para evaluar PDF en cualquier valor. En el siguiente ejemplo,
estamos calculando pdf de -50 a 50 para fines de trazado.

>>> x = np.linspace(-50,50, 1000) >>> y1 =


rv1.pdf(x) >>> y2 = rv2.pdf(x) >>> y3 = rv3.pdf(x)

Ahora, tenemos PDF estimado, se puede trazar. En el eje x ÿ mantendremos la variable, y en el eje y ÿ
mantendremos la PDF. También proporcionamos el argumento adicional lw a la función plot, que representa el
ancho de la línea y se utiliza para controlar los anchos del gráfico. La figura 5.7 muestra la PDF de tres variables
aleatorias distribuidas normalmente con parámetros de escala variables. La figura
Machine Translated by Google

5.2. Distribuciones teóricas 49

ilustra el efecto del parámetro de escala en el PDF. En el caso de un parámetro de escala menor, se concentra
más masa de pdf en el centro, a medida que aumenta el parámetro de escala, aumenta la dispersión.

>>> plt.trazar(x, y1, lw=3, etiqueta='escala=5') >>> plt.trazar(x,


y2, lw=3, etiqueta='escala=3') >>> plt .plot(x, y3, lw=3,
label='escala=7') >>> plt.xlabel('X', tamaño de fuente=20)
>>> plt.ylabel('PDF', tamaño de fuente=15) > >> plt.leyenda()
>>> plt.savefig('/home/tomer/articles/python/tex/images/
norm_pdf.png')

Figura 5.7: PDF para distribución normal con varios parámetros de escala.

Podemos usar la misma instancia para obtener también el CDF. El método cdf proporciona la CDF en la entrada
dada, que podría ser un escalar o una matriz. La CDF se muestra en la Fig. 5.8. CDF también muestra el efecto
del parámetro de escala, pero PDF proporciona un mejor interior. Por lo tanto, siempre es mejor graficar PDF para
ver el comportamiento de la distribución o de los datos empíricos.

>>> y1 = rv1.cdf(x) >>> y2


= rv2.cdf(x) >>> y3 =
rv3.cdf(x)
>>>
>>> # dibujar el pdf >>>
plt.clf() >>> plt.plot(x, y1,
lw=3, label='scale=5') >>> plt.plot(x, y2, lw =3,
etiqueta='escala=3') >>> plt.plot(x, y3, lw=3, etiqueta='escala=7')
>>> plt.xlabel('X', tamaño de fuente=20) > >> plt.ylabel('PDF',
tamaño de fuente=15) >>> plt.legend() >>> plt.savefig('/home/
tomer/articles/python/tex/images/norm_cdf.png')

Hay otras distribuciones silenciosas de uso común en hidrología, por ejemplo, Cauchy, Chi, Exponencial y Uniforme,
etc. Juguemos también con ellas. Primero generaremos una instancia de estas distribuciones. La distribución de
chi también requiere un parámetro de grado de libertad además de los parámetros de ubicación y escala.
En caso de distribución uniforme, el parámetro de ubicación se define como rango inferior y el parámetro de escala
Machine Translated by Google

50 Capítulo 5. Estadísticas

Figura 5.8: CDF de distribución normal para varios parámetros de escala.

se define como rango superior, lo cual no es cierto matemáticamente, y se define solo para facilitar las cosas al
proporcionar información para la función. La Fig.5.9 muestra el PDF de estas distribuciones.

>>> rv1 = st.cauchy(loc=0, escala=5) >>> rv2 =


st.chi(2, loc=0, escala=8) >>> rv3 = st.expon(loc=0,
escala =7) >>> rv4 = st.uniforme(loc=0, escala=20)

>>>
>>> # calcular pdf >>>
y1 = rv1.pdf(x) >>> y2 =
rv2.pdf(x) >>> y3 =
rv3.pdf(x) >>> y4 = rv4.pdf(x)

>>>
>>> # dibujar el pdf >>>
plt.plot(x, y1, lw=3, label='Cauchy') >>> plt.plot(x, y2, lw=3,
label='Chi') > >> plt.plot(x, y3, lw=3, label='Exponencial') >>>
plt.plot(x, y4, lw=3, label='Uniforme') >>> plt.xlabel('X ', tamaño de
fuente=20) >>> plt.ylabel('PDF', tamaño de fuente=15) >>>
plt.legend() >>> plt.savefig('/home/tomer/articles/python/tex/images/
pdf_todo.png')

Generamos un número de variables aleatorias de alguna distribución para representar la distribución.


Para explorar el impacto del número de muestras en la distribución empírica, generaremos números
aleatorios a partir de la misma distribución pero con varios números de muestras, y veremos cómo
afecta la distribución empírica. No usaremos ninguna medida cuantitativa para verificar esto, ya que
hasta esta etapa no hemos hablado de ellos, sino que solo los visualizaremos gráficamente. Primero
jugaremos con la distribución normal, que es la distribución más utilizada. Usaremos la función hist de
la biblioteca matplotlib.pyplot para calcular el PDF. Estamos especificando normed=1 para la función
hist, lo que significa que el área del histograma debe hacerse igual a uno, y que resulta ser el PDF.
También estamos usando plt.axis para especificar los límites de la gráfica, y lo mantenemos igual para
que podamos comparar las gráficas fácilmente. El argumento para plt.axis es [xmin, xmax, ymin , ymax ]. Higo.
Machine Translated by Google

5.2. Distribuciones teóricas 51

Figura 5.9: PDF para varias distribuciones.

5.10 muestra la PDF empírica y teórica para una muestra igual a 100, 1000, 10 000 y 100 000.
Está claro en la figura que a medida que aumenta el número de muestras, la distribución empírica se acerca a
la teórica. Con 100 muestras, la distribución está muy mal representada por los datos, mientras que en otros
casos es relativamente mejor.

>>> importar numpy como np


>>> importar matplotlib.pyplot como plt >>>
importar scipy.stats como st
>>>
>>> # distribución normal >>> rv =
st.norm(loc=0, scale=5)
>>>
>>> x1 = np.linspace(-20, 20, 1000) >>> y1 =
rv.pdf(x1)
>>>
>>> # calcular y trazar pdf >>> fig =
plt.figure() >>>
fig.subplots_adjust(wspace=0.4)
>>>
>>> plt.subplot(2,2,1) >>> x =
rv.rvs(tamaño=100) >>> n,
contenedores, parches = plt.hist(x, 20, normalizado=1, facecolor=' amarillo', alfa=0.5) >>> plt.plot(x1, y1, 'r',
lw=3) >>> plt.xlabel('X', tamaño de fuente=15) >>> plt.ylabel('PDF ', tamaño de fuente=15) >>> plt.axis([-20, 20,
0, 0.10]) >>> plt.texto(-18,0.08,'n=100')

>>>
>>> plt.subplot(2,2,2) >>> x =
rv.rvs(tamaño=1000) >>> n,
contenedores, parches = plt.hist(x, 20, normalizado=1, facecolor=' verde', alfa=0.5) >>> plt.plot(x1, y1, 'r', lw=3)
>>> plt.xlabel('X', tamaño de fuente=15) >>> plt.ylabel('PDF ', tamaño de fuente=15)
Machine Translated by Google

52 Capítulo 5. Estadísticas

>>> plt.eje([-20, 20, 0, 0.10]) >>>


plt.texto(-18,0.08,'n=1000')
>>>
>>> plt.subplot(2,2,3) >>> x
= rv.rvs(tamaño=10000) >>> n,
contenedores, parches = plt.hist(x, 20, normado=1, facecolor=' negro', alfa=0.5) >>> plt.plot(x1, y1, 'r',
lw=3) >>> plt.xlabel('X', tamaño de fuente=15) >>> plt.ylabel('PDF ', tamaño de fuente=15) >>> plt.eje([-20,
20, 0, 0.10]) >>> plt.texto(-18,0.08,'n=10000')

>>>
>>> plt.subplot(2,2,4) >>> x
= rv.rvs(tamaño=100000) >>> n,
bins, patches = plt.hist(x, 20, normad=1, facecolor=' magenta', alfa=0.5) >>> plt.plot(x1, y1, 'r', lw=3) >>>
plt.xlabel('X', tamaño de fuente=15) >>> plt.ylabel('PDF ', tamaño de fuente=15) >>> plt.eje([-20, 20, 0, 0.10])
>>> plt.texto(-18,0.08,'n=10000')

>>>
>>> plt.savefig('/home/tomer/my_books/python_in_hydrology/images/rand_theo.png')

Figura 5.10: Efecto del número de muestras (n) sobre la PDF empírica frente a la PDF teórica.

También podemos ver el efecto del número de muestras en la distribución empírica aparte de la distribución
normal, digamos la distribución de Laplace. En este ejemplo, estamos controlando los límites del eje
utilizando plt.xlim y plt.ylim por separado. En el caso del eje y, solo estamos definiendo ymax para controlar
el límite máximo del eje, mientras que para el eje x estamos definiendo ambos límites. El límite del eje
podría haberse fijado usando el eje como se usó en el último ejemplo, esto es solo para mostrar que
podemos controlar solo un límite y dejar el otro límite a plt. La Fig. 5.11 muestra la función de densidad de
probabilidad empírica y teórica para varios números de muestras.

>>> rv = st.laplace(loc=0, scale=15) >>> x1 =


np.linspace(-100, 100, 1000) >>> y1 = rv.pdf(x1)
Machine Translated by Google

5.2. Distribuciones teóricas 53

>>>
>>> # calcular y trazar pdf >>>
plt.clf() >>> fig = plt.figure() >>>
fig.subplots_adjust(wspace=0.4)

>>>
>>> plt.subplot(2,2,1) >>> x
= rv.rvs(tamaño=100) >>> n,
contenedores, parches = plt.hist(x, 20, normalizado=1, facecolor=' amarillo', alfa=0.5) >>> plt.plot(x1, y1,
'r', lw=3, etiqueta='escala=5') >>> plt.xlabel('X', tamaño de fuente=15) > >> plt.ylabel('PDF', tamaño de
fuente=15) >>> plt.ylim(ymax=0.04) >>> plt.xlim((-100,100)) >>> plt.text(-80,0.035,' n=100')

>>>
>>> plt.subplot(2,2,2) >>> x
= rv.rvs(tamaño=1000) >>> n,
contenedores, parches = plt.hist(x, 20, normalizado=1, facecolor=' verde', alfa=0.5) >>> plt.plot(x1, y1, 'r',
lw=3, etiqueta='escala=5') >>> plt.xlabel('X', tamaño de fuente=15) > >> plt.ylabel('PDF', tamaño de
fuente=15) >>> plt.ylim(ymax=0.04) >>> plt.xlim((-100,100)) >>> plt.text(-80,0.035,' n=1000')

>>>
>>> plt.subplot(2,2,3) >>> x
= rv.rvs(tamaño=1000) >>> n,
contenedores, parches = plt.hist(x, 20, normado=1, facecolor=' negro', alfa=0.5) >>> plt.plot(x1, y1, 'r',
lw=3, label='scale=5') >>> plt.xlabel('X', fontsize=15) > >> plt.ylabel('PDF', tamaño de fuente=15) >>>
plt.ylim(ymax=0.04) >>> plt.xlim((-100,100)) >>> plt.text(-80,0.035,' n=10000')

>>>
>>> plt.subplot(2,2,4) >>> x
= rv.rvs(tamaño=10000) >>> n,
contenedores, parches = plt.hist(x, 20, normado=1, facecolor=' magenta', alfa=0.5) >>> plt.plot(x1, y1, 'r',
lw=3, label='scale=5') >>> plt.xlabel('X', fontsize=15) > >> plt.ylabel('PDF', tamaño de fuente=15) >>>
plt.ylim(ymax=0.04) >>> plt.xlim((-100,100)) >>> plt.text(-80,0.035,' n=100000')

>>>
>>> plt.savefig('/home/tomer/my_books/python_in_hydrology/laplace_rand.png')
Machine Translated by Google

54 Capítulo 5. Estadísticas

Figura 5.11: Efecto del número de muestras sobre la PDF empírica frente a la PDF teórica para la distribución
de Laplace.

5.3 La prueba t

En estadística, hacemos hipótesis como si dos variables aleatorias diferentes tuvieran la misma media, o la
misma varianza, o siguieran la misma distribución. Para probar estas hipótesis, se deriva la estadística de
prueba y, en función de la estadística de prueba, se rechaza o acepta la hipótesis. Cuando el estadístico de
prueba sigue una distribución t de Student, la prueba t se usa para probar hipótesis. Esta prueba está disponible
en la biblioteca scipy.stats. Primero probemos si la media de la variable aleatoria es la misma que esperábamos
o no. La función st.ttest_1samp se utiliza para este propósito. Generaremos una variable aleatoria distribuida
normalmente con una media igual a 5 y una desviación estándar igual a 10. Y probaremos si la media de esta
variable aleatoria generada es 5 o no. Como estamos hablando de 1000 números de muestra, esperamos que
la media sea aproximadamente igual a 5 la mayor parte del tiempo (pero no siempre). La hipotetis se rechaza o
se acepta en función del valor p. El valor p cercano a uno significa que la hipótesis es verdadera; un valor más
cercano a cero significa que se rechaza la hipótesis. El nivel de significación (ÿ) se utiliza para definir el umbral,
que a menudo se toma como 0,05 o 0,01. Si el valor p es mayor que esto, entonces podemos aceptar la
hipótesis.

>>> importar scipy.stats como st >>>


rvs1 = st.norm.rvs(loc=5,scale=10,size=1000) >>> # t-test

>>> t, p = st.ttest_1samp(rvs1,5) >>> print(p)


0.882877605761

Vemos en este ejemplo que el valor p es 0.88, lo que significa que la media de la variable aleatoria generada
está cerca de 5. La prueba t también se usa para probar si la media de dos números aleatorios independientes
es igual o no. Generemos dos variables aleatorias distribuidas normalmente con la misma media, digamos 5.
Nos gustaría ver si la media de estas dos variables aleatorias independientes es la misma o no. Podemos usar
st.ttest_ind para este propósito. En este ejemplo, el valor p es 0,96, lo que significa que las medias son las mismas.

>>> rvs1 = st.norm.rvs(loc=5,scale=10,size=1000) >>> rvs2 =


st.norm.rvs(loc=5,scale=10,size=1000) >>> # prueba t

>>> t, p = st.ttest_ind(rvs1,rvs2) >>> imprimir(p)


Machine Translated by Google

5.4. prueba de KS 55

0.963392592667

En el ejemplo anterior, probamos la media de dos muestras independientes. También podemos probar si la media es la
misma o no, cuando las muestras están relacionadas o provienen del mismo experimento. Podemos usar st.ttest_rel para
este propósito. Obtenemos un valor de p de 0,57, lo que significa que las medias son las mismas.

>>> rvs1 = st.norm.rvs(loc=5,scale=10,size=1000) >>> rvs2 =


st.norm.rvs(loc=5,scale=10,size=1000) >>> # prueba t >>> t, p =
st.ttest_rel(rvs1,rvs2) >>> print(p) 0.569900697821

5.4 Prueba KS

La prueba KolmogorovSmirnov (KS) es una prueba no paramétrica para comparar la igualdad de dos distribuciones de
probabilidad unidimensionales continuas. En esta prueba, cuantificamos la distancia (diferencia absoluta) entre
distribuciones. Estas dos distribuciones podrían ser dos muestras diferentes, o una podría ser una muestra y otra una
distribución teórica. Probemos si nuestra variable aleatoria normal generada sigue una distribución normal o no. st.kstest
es la función para realizar la prueba KS.

>>> importar numpy como np >>>


importar scipy.stats como st >>> x =
np.random.randn(1000)
>>> # prueba de KS
>>> D, p = st.kstest(x,'norma') >>> print(p)
0.652473310995

Obtenemos un valor p igual a 0,65, lo que significa que nuestra variable aleatoria distribuida normalmente generada es, de
hecho, normal. También podemos probar si las variables aleatorias distribuidas uniformemente generadas no son normales
por casualidad. En esto obtenemos un valor p igual a 0, lo que significa que nuestros números aleatorios generados en
este caso no son normales.

>>> y = np.aleatorio.rand(1000)
>>> D, p = st.kstest(y,'norma') >>> print(p) 0.0

5.5 La prueba de chi cuadrado

También podemos comparar la distribución comparando sus PDF. En este caso, usamos las estadísticas de Chi cuadrado
2 2
(x ) prueba. En esta prueba, ÿ que se calculan primero y, en base a esto, decimos si las distribuciones son iguales o no.
Podemos comparar muestra con la distribución teórica, o dos muestras. Tomaremos dos pdfs, en los que se supone que
se observa uno y se espera otro. Usaremos la función chisquare de la biblioteca scipy.stats.mstats. Esta función proporciona
2
estadísticas de ÿ y
Machine Translated by Google

56 Capítulo 5. Estadísticas

p-valor de la prueba. En el siguiente ejemplo, obtenemos un valor p cercano a cero, lo que significa que estas
dos frecuencias provienen de distribuciones diferentes.

>>> from scipy.stats.mstats import chisquare >>> import


numpy as np >>> f_obs = np.array([10, 15, 20, 30]) # pdf
observado >>> f_exp = np.array([ 10, 5, 15, 30]) # pdf esperado >>> #
prueba chi cuadrado >>> c, p = chicuadrado(f_obs, f_exp)

>>>
>>> imprimir(c,p)
(21.666666666666668, 7.6522740548062336e-05)

5.6 Medida de dependencia estadística


Muchas veces nos interesa saber si dos variables hidrológicas son dependientes o no. En esta sección,
se describirá para comprobar su dependencia estadística. Si dos variables son estadísticamente
dependientes, no significa que también sean físicamente dependientes. Primero generaremos dos
variables que tengan diferente relación entre ellas. Pocas con perfecta relación, y pocas con algún ruido añadido.
En el siguiente ejemplo, estamos creando seis variables:

• Relación lineal perfecta (y = a+bx),

• Relación lineal con algo de ruido (y = a+bx+ÿ),


2
• Relación cuadrática que es monótona (y = x ),
2
• Relación cuadrática con algún ruido (y = x +ÿ),
2
• Relación cuadrática pero esta no es monótona (y = (xÿ5) ), y
2
• Ruido añadido al anterior (y = (xÿ5) +ÿ).

La figura 5.12 muestra estas variables. De las seis variables, tres tienen una relación perfecta y tres tienen
algo de ruido. Esperaríamos que nuestra medida de dependencia estadística revelara esto.

>>> importar numpy como np


>>> importar matplotlib.pyplot como plt
>>>
>>> x = np.linspace(0,10) >>> y1
= 2*x >>> y2 = y1 +
2*np.random.randn(50) >>> y3 = x**2 >>> y4
= y3 + 2*np.aleatorio.aleatorio(50) >>> y5 =
(x-5)**2 >>> y6 = y5 + 2*np.aleatorio.aleatorio(50)

>>>
>>> plt.subparcela(2,3,1)
>>> plt.parcela(x, y1, '.') >>>
plt.texto(2,15,'(a)')
Machine Translated by Google

5.6. Medida de dependencia estadística 57

>>>
>>> plt.subparcela(2,3,2)
>>> plt.parcela(x, y2, '.') >>>
plt.texto(2,15,'(b)')
>>>
>>> plt.subparcela(2,3,3)
>>> plt.parcela(x, y3, '.') >>>
plt.texto(2,80,'(c)')
>>>
>>> plt.subparcela(2,3,4)
>>> plt.parcela(x, y4, '.') >>>
plt.texto(2,100,'(d)')
>>>
>>> plt.subparcela(2,3,5)
>>> plt.parcela(x, y5, '.') >>>
plt.texto(2,20,'(e)')
>>>
>>> plt.subplot(2,3,6) >>>
plt.plot(x, y6, '.') >>>
plt.text(2,25,'(f)') >>> plt. savefig('/
home/tomer/my_books/python_in_hydrology/images/corr.png')

Figura 5.12: Diferente tipo de relación entre dos variables.

Desafortunadamente, no existe una medida para revelar la fuerza de la relación en caso de no linealidad.
La razón de esto es que podemos tener cualquier forma de relación no lineal que no sea posible para
medir a cantidad. Dicho esto, hay algunas medidas que funcionan bien en algunos casos. Exploraremos
algunos de ellos. Primero comience con el coeficiente de correlación de Pearson, que proporciona la
fuerza de la relación lineal. La función st.pearsonr se puede utilizar para calcular el coeficiente de
correlación de Pearson. Esta función también proporciona el valor p, que se puede utilizar para cuantificar
la importancia de la relación. Estamos utilizando el operador % para formatear la salida. .2f le dice a
imprimir la salida hasta el segundo lugar decimal.

>>> importar scipy.stats como st >>>


r1, p1 = st.pearsonr(x,y1) >>> r2, p2 =
st.pearsonr(x,y2)
Machine Translated by Google

58 Capítulo 5. Estadísticas

>>> r3, p3 = st.pearsonr(x,y3) >>> r4, p4 =


st.pearsonr(x,y4) >>> r5, p5 = st.pearsonr(x,y5)
>>> r6, p6 = st.pearsonr(x,y6)

>>>
>>> # imprime r >>>
imprime('%.2f %.2f %.2f %.2f %.2f %.2f')%(r1,r2,r3,r4,r5,r6) 1.00 0.97 0.97 0.96 0,00 -0,02

Obtenemos 1,0 para el primer caso y un valor ligeramente inferior a 1,0 para el segundo caso, porque perturbamos la
relación. En el tercer caso, obtenemos un valor de 0,97, cuando en realidad la relación es perfecta aunque no lineal. El
valor es 0 en el quinto caso, aunque la relación sea perfecta. Entonces podemos concluir que el coeficiente de correlación
de Pearson es bueno solo para medir la relación lineal. Ahora calcularemos el coeficiente de correlación de Spearman
para estos seis casos usando st.spearman.

>>> rho1, p1 = st.spearmanr(x,y1) >>> rho2, p2 =


st.spearmanr(x,y2) >>> rho3, p3 =
st.spearmanr(x,y3) >>> rho4, p4 =
st.spearmanr(x,y4) >>> rho5, p5 =
st.spearmanr(x,y5) >>> rho6, p6 = st.spearmanr(x,y6)

>>>
>>> # imprime los rho
>>> imprime('%.2f %.2f %.2f %.2f %.2f %.2f')%(rho1,rho2,rho3,rho4,rho5,rho6) 1.00 0.97 1.00 0.99 0,01 -0,04

El coeficiente de correlación de Spearman proporciona un resultado similar al de Spearman, excepto que es capaz de
reconocer mejor la relación en el tercer y cuarto caso. En el tercer y cuarto caso, la relación no fue lineal sino monótona.
El coeficiente de correlación de Spearman es una medida útil cuando los datos tienen un comportamiento monótono.
Pero esto tampoco funciona correctamente cuando la relación está bien definida, pero no es monótona. El coeficiente
de correlación tau de Kendall es una estadística para medir la correlación de rango. La tau de Kendall se puede calcular
mediante la función st.kendalltau.

>>> tau1, p1 = st.kendalltau(x,y1) >>> tau2, p2 =


st.kendalltau(x,y2) >>> tau3, p3 = st.kendalltau(x,y3)
>>> tau4, p4 = st.kendalltau(x,y4) >>> tau5, p5 =
st.kendalltau(x,y5) >>> tau6, p6 = st.kendalltau(x,y6)

>>>
>>> # imprime tau >>>
imprime('%.2f %.2f %.2f %.2f %.2f %.2f')%(tau1,tau2,tau3,tau4,tau5,tau6)
1,00 0,86 1,00 0,95 0,01 -0,05

Esto proporciona una medida similar a la del coeficiente de correlación de Spearman y no puede revelar la relación no
monótona que tenemos en el caso quinto y sexto.
Machine Translated by Google

5.7. regresión lineal 59

5.7 Regresión lineal


La regresión lineal es un enfoque para modelar la relación entre dos variables usando una función lineal. Usaremos la
función st.linregress para realizar una regresión lineal. Primero generaremos algunos datos sintéticos usando un modelo
lineal conocido, y también agregaremos algo de ruido usando una variable aleatoria normalmente distribuida. linregress
proporciona correlación, valor p y error estándar de estimación además de los coeficientes del modelo.

>>> importar numpy como np


>>> importar scipy.stats como st >>> #
generar los datos >>> n = 100 # longitud
de los datos >>> x = np.random.rand(n) >>> y =
3 + 7*x + np.random.randn(n) >>> # realiza una
regresión lineal >>> b, a, r, p, e = st.linregress(x, y)
>>> print(a b) (2.9059642495310403,
7.3015273619236618)

Generamos datos utilizando el modelo lineal (y = 3 + 7x + ÿ), mientras que la regresión lineal (y = 2.91 + 7.3x).
La diferencia entre el modelo ajustado y el modelo real se debe al ruido. A medida que agregue más ruido, verá que el
modelo ajustado se aleja más de la realidad. La figura 5.13 muestra la línea verdadera (y = 3 + 7x), la medición corrupta
(y = 3 + 7x + ÿ), la línea ajustada (y = 2,91 + 7,3x) y el intervalo de predicción para la línea ajustada. La línea ajustada y
la línea verdadera coinciden razonablemente. El intervalo de predicción también es bastante razonable.

La varianza de un Ypred pronosticado viene dada por,

2
2 (X0 ÿX)
ÿ
2
= E[(Ypred ÿYb) 2 ] = ÿ 1 1+ + ÿ . (5.1)
anterior ÿ norte
2
yo=1 (XÿX)
norte

2 2 2 el clásico estimador insesgado de la varianza residual. El ÿ pred


Donde, el ÿ ÿ
se estima por s
se usa para generar un intervalo de predicción usando una distribución t de Student con nÿ2 grados de libertad (porque
2
s es un estimador). El intervalo de confianza alrededor de Ypred está dado por,

PI = ÿpred ÿ z (5.2)

donde, PI es el intervalo de predicción, z es el valor de la distribución t de Student en el nivel de significancia ÿ.

>>> eps = y - a - b*x # error de ajuste y datos medidos >>> x1 = np.linspace(0, 1) # eje x
para trazar el PI >>> # varianza del error de ajuste >>> e_pi = np.var(eps)*(1+1.0/n + (x1-
x.media())**2/np.sum((xx.media())**2)) >>> # z valor usando la distribución t y con dof =
n-2 >>> z = st.t.ppf(0.95, n-2) >>> # intervalo de predicción >>> pi = np.sqrt(e_pi)*z >> > zl = st.t.ppf(0.10, n-2) # z
en 0.1 >>> zu = st.t.ppf(0.90, n-2) # z en 0.9 >>> ll = a + b*x1 + np.sqrt(e_pi)*zl # 10 % >>> ul = a + b*x1 +
np.sqrt(e_pi)*zu # 90 %
Machine Translated by Google

60 Capítulo 5. Estadísticas

Finalmente, podemos trazar la línea verdadera, la línea ajustada, la medición corrompida con ruido y los intervalos de
predicción.

>>> importar matplotlib.pyplot como plt >>>


plt.plot(x,y,'ro', label='medido') >>> plt.plot(x1,ll,'--',
label='10 %') >>> plt.plot(x1,ul,'--', label='90%') >>>
plt.xlabel('x') >>> plt.ylabel('y') >> > plt.legend(loc='mejor')
>>> plt.savefig('/home/tomer/my_books/
python_in_hydrology/images/lin_regress.png')

Figura 5.13: La línea ajustada junto con los intervalos de incertidumbre.

5.8 Regresión polinomial


Podemos hacer la regresión polinomial usando np.polyfit. Esto proporciona los coeficientes ajustados.
Podemos definir el orden del polinomio como tercer argumento de la función np.polyfit. Primero, estamos
2
generando un polinomio de segundo grado (y = 1+2xÿ3x ), entonces le agregamos ruido.

>>> importar numpy como np


>>> # generar datos >>> x =
np.linspace(0,10) >>> y = 1 + 2*x
- 3*x**2 + 15*np.random. randn(50) >>> # ajusta el polinomio >>> z
= np.polyfit(x,y,2) >>> print(z) [-3.03571947 1.34263078 4.58790632]

2
La función np.polyfit proporciona polinomio ajustado como y = 4.58 + 1.34x ÿ 3.03x coeficiente de , mientras que la

polinomios verdaderos eran diferentes. Sólo el tercer parámetro se calcula razonablemente.


Otros dos parámetros difieren mucho en comparación con el verdadero. Veamos el comportamiento de los
polinomios ajustados en comparación con el polinomio verdadero. La función np.poly1d se usa para evaluar el
polinomio usando el coeficiente ajustado devuelto por np.polyfit. La Fig. 5.14 muestra el gráfico resultante.
Machine Translated by Google

5.9. Interpolación 61

Aunque los coeficientes ajustados diferían de los coeficientes reales, el polinomio ajustado está bastante
cerca del verdadero. El parámetro asociado con el segundo grado fue calculado razonablemente por np.polyfit,
esto significa que este es el parámetro más sensible en comparación con otro.

>>> import matplotlib.pyplot as plt >>> # evaluar


polinomio >>> p = np.poly1d(z) >>> z_true =
np.array([-3, 2, 1]) # coeficiente de polinomio
verdadero > >> p_true = np.poly1d(z_true) # polinomio verdadero >>> # plot >>> plt.plot(x,
y,'.r', label='datos ruidosos') >>> plt.plot(x, p_true(x), label='Curva verdadera') >>> plt.plot(x,
p(x), label='Curva ajustada') >>> plt.xlabel('x') >>> plt.ylabel ('y') >>> plt.legend() >>>
plt.savefig('/home/tomer/my_books/python_in_hydrology/images/cuve_regre.png')

Figura 5.14: Curva ajustada junto con la curva verdadera y datos con ruido.

5.9 Interpolación
Hay varias formas de hacer la interpolación. Los métodos comúnmente utilizados son las funciones de base
radial, splines y lineales por partes. En esta sección, utilizaremos la función de base lineal y radial por partes
para interpolar los datos.

Primero generaremos algunos puntos de datos que tengan una relación exponencial. Luego interpolaremos
usando la función interp1d de la biblioteca scipy.interpolate. Esta función devuelve un objeto, que se puede
usar más tarde para evaluar la curva lineal por partes ajustada en los puntos de datos requeridos. La figura
5.15 muestra el polinomio ajustado por partes junto con los datos utilizados para generarlo.

>>> importar matplotlib.pyplot como plt >>>


importar numpy como np >>> from scipy.interpolate
import interp1d
Machine Translated by Google

62 Capítulo 5. Estadísticas

>>> # generar datos >>>


x = np.linspace(0,1,5) >>> y =
np.exp(-x) >>> f = interp1d(x, y)
>>> xnew = np .linspace(x.min(),
x.max()) >>> ynew = f(xnew) # usa la función de
interpolación devuelta por `interp1d` >>> # plot >>> plt.plot(x, y, ' ro', label='y') >>> plt.plot(xnuevo,
ynuevo, '-', label='ynuevo') >>> plt.xlabel('x') >>> plt.ylabel('y ') >>> plt.leyenda() >>> plt.savefig('/
home/tomer/my_books/python_in_hydrology/images/inter.png')

Figura 5.15: Curva interpolada frente a los datos medidos.

El inerp1d no hace extrapolación, es decir, emitirá un error si queremos ajustar los datos fuera del rango de
datos de entrada. Podemos suprimir el error especificando el argumentobounds_error=None. En este caso,
dará nan, si queremos interpolar fuera del rango de datos de entrada. Para interpolar fuera del rango de datos
de entrada, podemos usar la función Rbf de la biblioteca scipy.interpolate. Recuerde en la sección 4.4, los
datos interpolados solo estaban en el rango de ubicación de los datos de entrada. Usaremos la función Rbf
para interpolar fuera de este rango. Estamos usando plt.imshow para hacer el gráfico 2D. La figura 5.16
muestra el gráfico. Está claro a partir de la figura, que también es capaz de interpolar fuera del rango de
datos de entrada.

>>> x = np.aleatorio.rand(5) >>>


y = np.aleatorio.rand(5) >>> pet =
2+2*np.aleatorio.rand(5)
>>>
>>> rbfi = sp.interpolate.Rbf(x, y, pet) # instancia de interpolación de función de base radial
>>>
>>> xi = np.linspace(0,1) >>> yi =
np.linspace(0,1)
>>> XI, YI = np.meshgrid(xi,yi) # ubicaciones cuadriculadas
>>>
>>> di = rbfi(XI, YI) # valores interpolados
Machine Translated by Google

5.10. Autocorrelación 63

>>>
>>> plt.imshow(di, extensión=(0,1,0,1), origen='inferior') >>>
plt.dispersión(x,y, color='k') >>> plt.xlabel ('X') >>> plt.ylabel('Y') >>>
plt.axis((0,1,0,1)) >>> plt.savefig('/home/tomer/mis_libros/
python_en_hidrología/ imágenes/rbf.png')

Figura 5.16: Interpolación en 2D.

5.10 Autocorrelación
La autocorrelación es la correlación de una señal consigo misma. Esto indica cómo se relaciona una señal
en el tiempo o el espacio. Esto se puede usar para ver la periodicidad en la señal. Para demostrar esto,
primero generaremos una señal utilizando el seno con una periodicidad de 4ÿ y una magnitud de 2. La
figura 5.17 muestra la señal en el panel superior y la autocorrelación en el panel inferior. La autocorrelación
se traza utilizando la función plt.acorr. Hemos mostrado la cuadrícula en el gráfico usando la función
plt.grid.
autocorrelación muestra un buen Las líneas horizontales
comportamiento periódico ÿ1
conenuna
0 yperiodicidad
e se trazan usando
de 4ÿ. plt.axhline. La

>>> import numpy as np >>>


import matplotlib.pyplot as plt >>> x =
2*np.sin(np.arange(100)/2.0) # señal periódica >>> x += np.random.randn
(len(x)) # corrompido con ruido
>>>
>>> plt.subplot(2,1,1) >>>
plt.plot(x, '-s') >>> plt.ylabel('x',
fontsize=20) >>> plt.grid(True ) >>>
plt.xlabel('Tiempo')

>>>
>>> plt.subplot(2,1,2) >>> c
= plt.acorr(x, usevlines=True, normed=True, maxlags=50, lw=2) >>> plt.grid(True) > >>
plt.axhline(0, color='negro', lw=2)
Machine Translated by Google

64 Capítulo 5. Estadísticas

>>> plt.axhline(1/np.exp(1), color='rojo') >>>


plt.ylabel('Autocorrelación') >>> plt.xlim(xmin=0,xmax=100)
>> > plt.xlabel('Lag') >>> plt.savefig('/home/tomer/my_books/
python_in_hydrology/images/corr_0.png')

Figura 5.17: Gráfico que muestra 100 números aleatorios generados mediante la función seno y una
autocorrelación de la serie.

La función de autocorrelación también se utiliza para calcular la longitud de la correlación. La longitud de


correlación es la distancia desde un punto más allá del cual no hay más correlación de una propiedad física
asociada con ese punto. Matemáticamente, la longitud de la correlación es el retraso en el que la autocorrelación
ÿ1
mi , es igual a la que se muestra mediante una línea roja horizontal en el gráfico. Hagamos un gráfico con mayor
periodicidad para calcular la longitud de la correlación. El gráfico resultante se muestra en la Fig. 5.18. Gráficamente
vemos que la correlación es aproximadamente 9.

>>> import numpy as np >>>


import matplotlib.pyplot as plt >>> x =
2*np.sin(np.arange(100)/10.0) # señal periódica >>> x += np.random.randn
(len(x)) # corrompido con ruido
>>>
>>> plt.subplot(2,1,1) >>>
plt.plot(x, '-s') >>> plt.ylabel('x',
fontsize=20) >>> plt.grid(True ) >>>
plt.xlabel('Tiempo')

>>>
>>> plt.subplot(2,1,2) >>> c =
plt.acorr(x, usevlines=True, normed=True, maxlags=50, lw=2) >>> plt.grid(True) > >> plt.axhline(0,
color='negro', lw=2) >>> plt.axhline(1/np.exp(1), color='rojo') >>> plt.ylabel('Autocorrelación' ) >>>
plt.xlim(xmin=0,xmax=100) >>> plt.xlabel('Lag') >>> plt.savefig('/home/tomer/my_books/
python_in_hydrology/images/corr_1.png' )
Machine Translated by Google

5.10. Autocorrelación sesenta y cinco

Figura 5.18: Gráfico que muestra 100 números aleatorios generados mediante la función seno y una autocorrelación de
la serie.

Para determinar con precisión la longitud de la correlación, estaríamos ajustando una función de interpolación entre
ÿ1
el retraso y la longitud de la correlación, y luego determine el retraso donde la autocorrelación se convierte en e . los
La función plt.acorr devuelve retrasos y autocorrelación en estos retrasos. Primero asignaremos retrasos y
correlación con variables separadas. También imprimimos los lags para ver qué hay dentro.

>>> retrasos = c[0] # retrasos


>>> auto_corr = c[1] # autocorrelación
>>> imprimir(auto_corr)
[-50 -49 -48 -47 -46 -45 -44 -43 -42 -41 -40 -39 -38 -37 -36 -35 -34 -33
-32 -31 -30 -29 -28 -27 -26 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15
-14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 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]

La acorr proporciona retrasos positivos y negativos. No necesitamos ambos, podemos deshacernos de él dando un
index que está en formato booleano y se obtiene usando la sentencia lags>=0. También eliminamos
la matriz de autocorrelación que corresponde a los retrasos negativos.

>>> auto_corr = auto_corr[retrasos>=0]


>>> retrasos = retrasos[retrasos>=0]

Ahora, necesitamos la autocorrelación en dos puntos, uno justo por encima del umbral y otro justo por debajo del
límite. Obtenemos sus índices contando cuántas veces la correlación automática está por encima del umbral.

>>> n = suma(auto_corr>np.exp(-1))
>>> imprimir(n)
9

Un punto está en el octavo índice y otro en el noveno índice. Ahora, podemos usar interp1d para obtener el valor
de retraso exacto cuando la autocorrelación es igual al umbral. Esto proporciona la longitud de correlación que
es 8.65.

>>> f = interp1d([auto_corr[n], auto_corr[n-1]], [retrasos[n], retrasos[n-1]])


Machine Translated by Google

66 Capítulo 5. Estadísticas

>>> corr_len = f(np.exp(-1))


arreglo(8.64725236367028)

5.11 Intervalos de incertidumbre

Muchas veces, obtenemos una serie de conjuntos de datos. Y queremos ver el comportamiento de estos conjuntos.
Comencemos primero por generar conjuntos y luego trazarlos. En este ejemplo, primero estamos generando una
señal con comportamiento de pecado. Luego, estamos usando vstack para apilar los datos, es decir, para hacer
una matriz bidimensional utilizando muchas matrices unidimensionales. Después de esto, mezclamos algo de ruido
en los datos para que el conjunto se vea ligeramente diferente. Estamos transponiendo los datos usando atributos
T para trazar; de lo contrario, trazará el conjunto en el eje x en lugar del tiempo.

>>> importar numpy como np


>>> importar matplotlib.pyplot como plt >>> importar
scipy.stats como st
>>>
>>> # generar algunos datos >>>
x = 100*np.sin(np.linspace(0,10,100))
>>> X = np.vstack([x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x] ) >>> e =
10*np.aleatorio.randn(20,100)
>>>
>>> X_err = X+e
>>>
>>> plt.plot(X_err.T, 'k') >>>
plt.xlabel('Tiempo') >>> plt.ylabel('X')
>>> plt.savefig('/home/tomer/
mis_libros/python_in_hydrology/images/X_err.png')

Figura 5.19: Varios conjuntos de datos.

La Fig. 5.19 muestra la gráfica de estos conjuntos. Vemos que todo el conjunto se está comportando de manera
similar a cada uno. Pero no podemos inferir nada más sobre el comportamiento del conjunto usando esta trama.
Una mejor manera de visualizar el conjunto es usar los diversos intervalos de incertidumbre junto con la media.
Podemos calcular el intervalo de incertidumbre en varios percentiles usando la función st.scoreatpercentile.
Machine Translated by Google

5.11. Intervalos de incertidumbre 67

Estamos calculando los percentiles 10, 50 y 90 . El percentil 50 es la mediana. Estamos graficando la mediana que la
media, porque si hay algunos valores atípicos en los datos, la mediana proporcionó una mejor comprensión del
comportamiento del conjunto. La figura 5.20 muestra la mediana, el 10 y el 90 del conjunto. Usando esta gráfica,
podemos notar que los diferenciales del conjunto no son iguales en todas partes; es relativamente más en el pico y el
valle y menos en otros lugares.

>>> ll = st.scoreatpercentil(X_err, 10) # 10th percentil >>> ml = st.scoreatpercentil(X_err,


50) # 50th percentil >>> ul = st.scoreatpercentil(X_err, 90) # 90th percentil

>>>
>>> plt.plot(ml, 'g', lw=2, label='Median') >>> plt.plot(ul, '--m',
label='90%') >>> plt. plot(ll, '--b', label='10%') >>> plt.xlabel('Tiempo')
>>> plt.ylabel('X') >>> plt.legend(loc='mejor ') >>> plt.savefig('/
home/tomer/my_books/python_in_hydrology/images/X_uncer.png')

Figura 5.20: La mediana y los intervalos de incertidumbre de los datos estimados a partir del conjunto.

Los intervalos de incertidumbre podrían trazarse mediante regiones sombreadas. plt.fill_ between ofrece la opción de
rellenar el color entre dos matrices y se puede utilizar para crear regiones sombreadas.

>>> plt.trazar(ml, 'g', lw=2, etiqueta='Mediana') >>>


plt.llenar_entre(rango(100), ul, ll, color='k', alfa=0.4, etiqueta ='90%') >>> plt.xlabel('Tiempo') >>> plt.ylabel('X') >>>
plt.legend(loc='mejor') >>> plt.savefig('/ home/tomer/my_books/python_in_hydrology/images/X_uncer_shade.png')

La figura 5.21 muestra la gráfica de incertidumbre utilizando la región sombreada.


Machine Translated by Google

68 Capítulo 5. Estadísticas

Figura 5.21: La mediana y los intervalos de incertidumbre de los datos estimados a partir del conjunto. Los intervalos de
incertidumbre se muestran utilizando la región sombreada.
Machine Translated by Google

Capítulo 6

Datos espaciales

6.1 Tipos de datos espaciales

Raster y vector son las dos estructuras de datos básicas para almacenar y manipular imágenes y datos
gráficos en GIS (Sistemas de Información Geográfica). La imagen ráster viene en forma de píxeles
individuales, y cada ubicación espacial o elemento de resolución tiene un píxel asociado donde el valor del
píxel indica el atributo, como el color, la elevación o un número de identificación. Los datos vectoriales vienen
en forma de puntos y líneas, que están asociados geométrica y matemáticamente. Los puntos se almacenan
usando las coordenadas, por ejemplo, un punto bidimensional se almacena como (x, y). Las líneas se
almacenan como una serie de pares de puntos, donde cada par representa un segmento de línea recta, por
ejemplo, (x1, y1) y (x2, y2) que indican una línea de (x1, y1) a (x2, y2).

Crearemos algunos datos ráster usando alguna función matemática y luego también agregaremos ruido.
Conservaremos los datos (con ruido y sin ruido) para uso futuro. np.mgrid se usa para crear puntos
cuadriculados. Los datos se trazan utilizando la función plt.matshow, que es una función simple para visualizar
una matriz bidimensional. La Fig. 6.1 muestra los datos sin ruido, los datos corruptos con ruido se muestran
en la Fig. 6.2. Los datos sin ruido muestran un comportamiento sistemático, mientras que se difumina en los
datos añadidos con ruido.

>>> importar numpy como np


>>> # generar algunos datos sintéticos >>> X,
Y = np.mgrid[0:101, 0:101] >>> data =
np.sin((X**2 + Y **2)/25) >>> data_noisy = data
+ np.random.random(X.shape)
>>>
>>> # trazar los datos >>>
plt.matshow(data) >>>
plt.colorbar() >>> plt.savefig('/
home/tomer/my_books/python_in_hydrology/images/spatial_data.png')
>>>
>>> plt.matshow(data_noisy) >>>
plt.colorbar(shrink=0.5) >>> plt.savefig('/
home/tomer/my_books/python_in_hydrology/images/spatial_data_noisy.png')
Machine Translated by Google

70 Capítulo 6. Datos espaciales

Figura 6.1: Datos sintéticos creados.

Figura 6.2: Datos sintéticos perturbados con ruido.

También podemos generar datos vectoriales usando algunos puntos. La figura 6.3 muestra los datos vectoriales.

>>> # datos vectoriales


>>> vector_x = [10,7,24,16,15,10] >>> vector_y =
[10,23,20,14,7,10]
>>>

>>> #trazar datos vectoriales


>>> plt.clf() >>> plt.plot(vector_x,
vector_y) >>> plt.axis((5,25,5,25)) >>> plt.savefig( '/
home/tomer/my_books/python_in_hydrology/
images/vect.png')
Machine Translated by Google

6.1. Tipos de datos espaciales 71

Figura 6.3: Datos vectoriales.

Los datos geoespaciales se pueden clasificar en dos partes principales. En la primera parte tenemos información sobre alguna
característica, como una matriz bidimensional que muestra la variación espacial en la elevación, etc. En la segunda parte, tenemos
información sobre las coordenadas de los datos. En el diagrama de flujo 6.4 se muestra una cadena típica de procesamiento de
datos geoespaciales. Tenemos los datos geoespaciales y extraemos la información de las características y coordinamos la
información por separado, luego los procesamos por separado y, finalmente, después de procesarlos, los combinamos nuevamente.
El procesamiento de la información de características podría ser una operación matemática, y para la información de coordenadas,
podría ser una transformación de coordenadas.
etc.

Datos geoespaciales

Coordinar la
Información de características
información

Procesando Procesando

Datos

geoespaciales procesados

Figura 6.4: Diagrama de flujo que muestra una cadena típica para procesar los datos geoespaciales.
Machine Translated by Google

72 Capítulo 6. Datos espaciales

6.2 Geoinformación
Los datos ráster se pueden georreferenciar especificando la variable GeoTransform o especificando los GCP
para la imagen. El GeoTransform (GT) está relacionado con las coordenadas geográficas de la siguiente manera,

Xgeo = GT[0] +Ximagen ÿGT[1] +Yimagen ÿGT[2], (6.1)

Ygeo = GT[3] +Ximagen ÿGT[4] +Yimagen ÿGT[5], (6.2)

donde, el subíndice geo se refiere a las coordenadas globales, y la imagen se refiere a las coordenadas de la
imagen, es decir, el píxel y el número de línea de la imagen. El número entre corchetes ([]) representa los índices
de las variables GT. X e Y son coordenadas. GT[2] y GT[4] representan la orientación de la imagen, con respecto
a X e Y de geo, y se vuelve cero si la imagen está al norte. GT[1] representa el ancho de píxel y GT[5] representa
la altura de píxel. GT[0] y GT[3] es la posición de la esquina superior izquierda del píxel superior izquierdo del
ráster. Cabe señalar que las coordenadas de píxel/línea de arriba van desde (0.0,0.0) en la esquina superior
izquierda del píxel superior izquierdo hasta la esquina inferior derecha del píxel inferior derecho. Por lo tanto, la
ubicación del píxel/línea del centro del píxel superior izquierdo sería (0,5, 0,5).

La información relacionada con la georreferenciación se puede especificar especificando los puntos de control.
Los puntos de control deben contener como mínimo GCPPixel (número de píxeles de la imagen), GCPLine
(número de línea de la imagen), GCPX (coordenada X), GCPY (coordenada Y) y GCPZ (coordenada Z). La
posición (píxel, línea) es la ubicación de GCP en el ráster. La posición (X,Y,Z) es la ubicación georreferenciada
asociada con la Z a menudo siendo cero. Por lo general, los polinomios se utilizan para transformar las
coordenadas de la imagen (píxel, línea) en coordenadas georreferenciadas.

Normalmente, un conjunto de datos contendrá una geotransformación afín o GCP. Además de la información
sobre cómo se relacionan las coordenadas con las coordenadas georreferenciadas, también se asigna a la
imagen el nombre del sistema de coordenadas.

6.3 Ráster de escritura


Hay varios formatos para almacenar los datos ráster; Geotiff es el más utilizado. Usaremos la biblioteca gdal
para leer y escribir los datos ráster. Compruebe si ha instalado gdal emitiendo el comando import gdal. Si no
obtiene ningún error, entonces todo está bajo control; de lo contrario, vaya a http://trac.osgeo.org/gdal/wiki/
DownloadSource, descargue e instale la última versión.
Primero escribamos los datos en formato GeoTIFF. Primero escribiremos los datos sin ruido.

>>> import gdal >>>


controlador = gdal.GetDriverByName('GTiff') >>> file_name
= "/home/tomer/my_books/python_in_hydrology/datas/data.tif" >>> dataset = driver.Create(file_name,
data.shape[1], data.shape[0], 1, ... gdal.GDT_Float32) >>> dataset.SetGeoTransform((664000.0, 100.0,
0.0, 1309000.0, 0.0, -100.0)) >>> dataset. GetRasterBand(1).WriteArray(datos, 0, 0) >>> conjunto de
datos = Ninguno

Primero creamos el controlador y le pedimos que creara un archivo GTIFF. También se pueden crear otros tipos
de formato. Una lista del formato soportado por gdal, y su código para crear el controlador son
Machine Translated by Google

6.4. vector de escritura 73

enumerado en http://www.gdal.org/formats_list.html, por ejemplo, el código para gráficos de red portátiles es PNG. Luego
creamos la base de datos, es decir, creamos el archivo en la computadora, emitiendo el comando dirver.Create. Las
entradas requeridas para Crear son el nombre del archivo, el tamaño de los datos, el número de banda en los datos, el
formato de los datos. Luego definimos la geoinformación emitiendo el comando SetGeoTransform. Y finalmente
escribimos los datos usando el método GetRasterBand.
Es una buena práctica cerrar los datos definiendo el conjunto de datos como Ninguno. Si la ruta para el nombre de
archivo especificado no existe, devuelve Ninguno y dará error si se realizan otras operaciones sobre él.

De manera similar, podemos escribir los datos corruptos con ruido.

>>> controlador = gdal.GetDriverByName('GTiff') >>> file_name


= "/home/tomer/my_books/python_in_hydrology/datas/data_noisy.tif" >>> dataset = driver.Create(file_name,
data_noisy.shape[1 ], data_noisy.shape[0], 1, gdal.GDT_Fl >>> dataset.SetGeoTransform((664000.0, 100.0, 0.0, 1309000.0, 0.0, -100.0)) >>>
dataset.GetRasterBand(1).WriteArray(data_noisy, 0, 0) >>> conjunto de datos = Ninguno

6.4 Vector de escritura


El formato Shapefile (.shp) es un tipo de datos vectoriales de uso común y silencioso. Escribamos un archivo de forma.
Para escribir el archivo de forma, usaremos el paquete ogr. OGR es parte de la biblioteca GDAL. OGR se ocupa de los
formatos vectoriales, mientras que la biblioteca principal de GDAL es para formatos ráster. En http://www.gdal.gdal se
proporciona una lista de formatos admitidos por OGR junto con su nombre de código que se usará al crear el controlador.
org/ogr/ogr_formats.html. Digamos que queremos hacer un archivo de forma que tenga la ubicación de las cuatro
ciudades y su nombre. Los detalles de las ciudades son los siguientes:

Nombre Latitud Longitud Bijnor 29,4 78,1


Delhi 28,6 77,2 Bangalore
Berambadi13,0
11,8
77,8
76,6

Comenzamos con la importación de la biblioteca ogr y la definición de la ubicación y los nombres de las ciudades.

>>> import ogr >>>


lat = [29.4,28.6,13.0,11.8] >>> lon =
[78.1,77.2,77.8,76.6] >>> nombre = ['Bijnor',
'Delhi', 'Bangalore' , 'Berambadi']

Ahora, definimos el nombre del controlador (ESRI Shapefile) y creamos la fuente de datos. driver.CrateDataSource define
el nombre de la carpeta donde se guardarán los datos. ds.CreateLayer define el nombre del archivo de forma junto con
el tipo de geometría (punto en este caso). Luego definimos el nombre del campo como 'Nombre' y decimos que es un
tipo de cadena que tiene un ancho máximo de 16.

>>> controlador = ogr.GetDriverByName("ESRI Shapefile") >>> ds =


controlador.CreateDataSource('/home/tomer/my_books/python_in_hydrology/datas/') >>> capa = ds.CreateLayer('ubicación',
geom_type=ogr.wkbPoint) >>> field_defn = ogr.FieldDefn('Name', ogr.OFTString ) >>> field_defn.SetWidth(16) >>>
capa.CreateField(field_defn)
Machine Translated by Google

74 Capítulo 6. Datos espaciales

Ahora, tenemos la información básica lista y podemos comenzar a agregar la información sobre las ciudades.
(nombre y ubicación). Primero creamos una función para almacenar la información sobre la ciudad. Luego, agregamos el
nombre de la ciudad en el campo 'Nombre'. Después de esto, decimos que es de tipo punto, y le sumamos su longitud
y latitud. Por último, destruimos la característica y la fuente de datos, para que no se pueda hacer nada más con
ellos, y nuestros datos se guardan correctamente.

>>> yo = 0

>>> for i in range(len(nombre)):


>>> función = ogr.Característica(capa.GetLayerDefn())
>>> característica.SetField('Nombre', nombre[i])
>>> pt = ogr.Geometría(ogr.wkbPoint)
>>> pt.SetPoint_2D(0, lon[i], lat[i])
>>> característica.EstablecerGeometría(pt)
>>> capa.CrearCaracterística(característica)
>>> función. Destruir ()
>>> ds.Destruir()

Podemos ver este shapefile en cualquier visor GIS. La Fig. 6.5 muestra la ubicación de las ciudades que fue
generado usando QGIS.

Figura 6.5: Ubicación de las ciudades.

6.5 Lectura del ráster


En esta sección, leeremos los datos que escribimos en la sección anterior. Leeremos los datos raster
que tiene ruido.
Machine Translated by Google

6.6. Leer el vector 75

>>> controlador = gdal.GetDriverByName('GTiff')


>>> file_name = "/home/tomer/my_books/python_in_hydrology/datas/data_noisy.tif"
>>> conjunto de datos = gdal.Open(file_name, GA_ReadOnly)
>>> geotransformación = conjunto de datos.GetGeoTransform()
>>> datos = conjunto de datos.GetRasterBand(1).ReadAsArray()
>>> conjunto de datos = Ninguno

6.6 Leer el vector


En esta sección, leeremos los datos vectoriales que escribimos anteriormente. Primero, necesitamos importar ogr
biblioteca. Luego abrimos la fuente de datos especificando el directorio del archivo de forma. Entonces, usamos
GetLayerByName para leer el archivo de forma especificando el nombre del archivo shpae sin la extensión .shp.
Después de esto, estamos imprimiendo \n lo que significa imprimir una línea en blanco. \n representa una nueva línea y \t
representa la pestaña. Ahora, estamos imprimiendo la información del encabezado (SI., Nombre, Latitud, Longitud). Estamos
usando .format para formatear la salida. El número dentro de '{}' después de los dos puntos (:) representa el
longitud de la salida. Luego leemos la característica en el archivo de forma uno por uno usando el ciclo for. De
cada característica, extraemos el nombre usando GetFieldAsString, Longitud usando GetX y Latitude
utilizando GetY. Al final para evitar corromper la base de datos, la cerramos de forma segura especificando la fuente de datos
como Ninguno.

>>> importar ogro


>>> ds = ogr.Open( '/home/tomer/my_books/python_in_hydrology/datas/' )
>>> lyr = ds.GetLayerByName('ubicación' )
>>>
>>> imprimir("\n")
>>> print("{} \t {:10s} \t {} \t {}".format('SI', 'Nombre', 'Longitud', 'Latitud'))
>>> para hazaña en lyr:
>>> geom = hazaña.GetGeometryRef()
>>> nombre = hazaña.GetFieldAsString(0)
>>> lat = geom.GetX()
>>> lon = geom.GetY()
>>> imprimir('{0} \t {1:10s} \t {2:.3f} \t \t {3:.3f}'.format(0, nombre, lat, lon ))
>>>
>>> ds = Ninguno

SI Nombre Latitud longitud


0 Bijnor 78.100 29.400
0 Delhi 77.200 28.600
0 Bangalore 77.800 13.000
0 Berambadí 76.600 11.800

6.7 Filtrado
Los datos del RADAR activo se ven afectados por moteado/ruido. Antes de extraer alguna información útil
de los datos satelitales, necesitamos eliminar/minimizar estas motas de los datos. Estos filtros
esencialmente trate de eliminar la información de alta frecuencia. En realidad, esta información de alta frecuencia
no tiene por qué ser ruido. Entonces necesitamos especificar cuánto filtrado queremos. Los tipos de filtro
se pueden dividir en dos categorías: filtros adaptativos y no adaptativos. Los filtros adaptables adaptan sus
Machine Translated by Google

76 Capítulo 6. Datos espaciales

ponderaciones en la imagen al nivel de motas, y los filtros no adaptativos aplican las mismas ponderaciones de manera
uniforme en toda la imagen. En esta sección, usaremos un ejemplo de ambas categorías.
Usaremos el filtro mediano de la categoría de filtro no adaptativo y el filtro Wiener de la categoría adaptativa.

Podemos importar la función medfilt2d desde la biblioteca scipy.signal. Primero, leemos los datos ruidosos que
guardamos en formato tif desde el disco duro. Luego le aplicamos un filtro con un tamaño de ventana de 3 × 3. La Fig.
6.6 muestra la imagen filtrada. Cuando comparamos esta imagen con la imagen original y con la imagen en la que
mezclamos algo de ruido, vemos que las imágenes filtradas mostraron una variación más suave, pero no se acercaron
mucho a la imagen original.

>>> desde osgeo import gdal >>>


desde scipy.signal import medfilt2d >>> desde
osgeo.gdalconst import * >>> import matplotlib.pyplot as
plt
>>>
>>> # leer los datos raster
>>> controlador = gdal.GetDriverByName('GTiff') >>> file_name
= "/home/tomer/my_books/python_in_hydrology/datas/data_noisy.tif" >>> dataset = gdal.Open(file_name, GA_ReadOnly)
>>> geotransform = conjunto de datos.GetGeoTransform() >>> datos = conjunto de datos.GetRasterBand(1).ReadAsArray()
>>> conjunto de datos = Ninguno

>>>
>>> data_median = medfilt2d(data, kernel_size=3) # filtro mediano de ventana 3X3 >>> # graficar los datos >>>
plt.matshow(data_median) >>> plt.colorbar() >>> plt.savefig( '/home/tomer/my_books/python_in_hydrology/images/
median.png')

Figura 6.6: Datos con ruido después de filtrar con el filtro mediano.
Machine Translated by Google

6.8. NDVI 77

Ahora, aplicamos el filtro Wiener en el mismo conjunto de datos. También mantenemos el mismo tamaño de ventana para el
filtro Wiener. Después de hacer el filtrado, también estamos guardando los datos en formato tif. Esto le dice cómo puede leer
algunos datos geoespaciales, procesar la información de la característica (matriz en este caso) y luego guardar la información
de la característica con la información de coordenadas.

>>> from scipy.signal import wiener >>> data_wiener


= wiener(data, mysize=(3,3)) # Wiener filter >>> # plot >>> plt.matshow(data_wiener) >>>
plt.colorbar( ) >>> plt.savefig('/home/tomer/my_books/python_in_hydrology/images/
wiener.png')

>>>
>>> # guardar los datos en formato tif >>> controlador
= gdal.GetDriverByName('GTiff') >>> file_name = "/home/tomer/
my_books/python_in_hydrology/datas/data_filtered.tif" >>> conjunto de datos = controlador .Create(file_name,
data_wiener.shape[1], data_wiener.shape[0], 1, gdal.GDT >>> dataset.SetGeoTransform(geotransform) >>>
dataset.GetRasterBand(1).WriteArray(data_wiener, 0, 0 ) >>> conjunto de datos = Ninguno

Figura 6.7: Datos con ruido después de filtrar con el filtrado de Wiener.

6.8 NDVI
El índice de vegetación de diferencia normalizada (NDVI) es un índice para analizar la variación en la vegetación.
La fórmula para calcular el NDVI es la siguiente:

NIR-ROJO
VND I = (6.3)
NIR+ROJO
Machine Translated by Google

78 Capítulo 6. Datos espaciales

Comenzamos con la importación de bibliotecas y no olvide importar la división de la biblioteca __future__.


Esto es para evitar la división de enteros. Luego leemos los datos que están en formato tiff. Para calcular NDVI,
necesitamos datos para NIR (banda 4) y RED (banda 3).

>>> # importar la biblioteca requerida >>> from


__future__ import division >>> from osgeo import
gdal >>> from osgeo.gdalconst import * >>> import
matplotlib.pyplot as plt

>>>
>>> # leer los datos raster de banda 3 >>> driver
= gdal.GetDriverByName('GTiff') >>> file_name = "/home/
tomer/my_books/python_in_hydrology/datas/band3.tif" >>> dataset = gdal .Open(file_name, GA_ReadOnly)
>>> geotransform = dataset.GetGeoTransform() >>> proyección = dataset.GetProjection() >>> band3 =
dataset.GetRasterBand(1).ReadAsArray() >>> dataset = Ninguno

>>> # leer los datos ráster de la banda 4 >>>


file_name = "/home/tomer/my_books/python_in_hydrology/datas/band4.tif" >>> dataset = gdal.Open(file_name,
GA_ReadOnly) >>> band4 = dataset .GetRasterBand(1).ReadAsArray() >>> conjunto de datos = Ninguno

Además de los datos, también estamos recuperando la información de geotransformación y proyección.


Imprimámoslos uno por uno.

>>> imprimir(geotransformar)
(76.5, 0.001, 0.0, 11.85, 0.0, -0.001)

La primera entrada en esto nos dice que la latitud y la longitud de la esquina noroeste son 11,85 y 76,5
respectivamente. La resolución de los datos es 0,001 en ambas direcciones x e y, y la imagen no tiene rotación.
Imprimamos ahora, información de proyección.

>>> imprimir (proyección)


GEOGCS["WGS 84",DATUM["desconocido",ESFEROIDE["WGS84",6378137,298.257223563]],
PRIMEM["Greenwich",0],UNIDAD["grado",0.0174532925199433]]

Esto nos dice que el datum de los datos es WGS84, y nuestros datos están en coordenadas geográficas (latitud y
longitud). Se pueden encontrar más detalles sobre las proyecciones y sus parámetros en http://spatialreference.org.

Podemos verificar el tipo de datos usando los atributos dtype. Vemos ese tipo de dato entero. Es por eso que
hemos importado la división de la biblioteca __future__, para evitar la división de enteros.

>>> imprimir(banda3.tipod)
uint8

Ahora calculamos NDVI y trazamos el resultado usando matshow. En matshow, también especificamos vmin y
vmax para controlar la extensión de la barra de colores.
Machine Translated by Google

6.8. NDVI 79

>>> ndvi = (banda4-banda3)/(banda4+banda3)


>>>
>>> plt.matshow(ndvi,cmap=plt.cm.jet, vmin=-1, vmax=1) >>>
plt.colorbar(shrink=0.8) >>> plt.savefig('/home/tomer/ mis_libros/
python_en_hidrología/images/ndvi.png')

Figura 6.8: Índice de vegetación de diferencia normalizada.


Machine Translated by Google

80 Capítulo 6. Datos espaciales


Machine Translated by Google

Capítulo 7

Graficado

El primer problema que tuvimos durante el trazado fue el tamaño de la fuente. Podemos cambiar el tamaño de fuente
especificando el método de tamaño de fuente de pyplot, pero para esto necesitamos especificar el tamaño de fuente en todas partes.
Esto se convierte en una tarea engorrosa, especialmente cuando quieres hacer muchas tramas. Hay otra forma de solucionar
este problema, actualizando el método prcParams de plt. La actualización se realiza de la siguiente manera.

>>> importar matplotlib.pyplot como plt >>> params =


{'axes.labelsize': 17,
>>> 'text.fontsize': 17,
>>> 'legend.fontsize': 17, 'xtick.labelsize':
>>> 17, 'ytick.labelsize': 17, 'text.usetex':
>>> Falso, 'font.size':17}
>>>
>>>
>>>

>>> plt.rcParams.update(parámetros)

El nombre de los parámetros se explica por sí mismo. Si queremos mantener el mismo tamaño de fuente para todo tipo de
texto (por ejemplo, marcas, etiquetas, leyendas, etc.), simplemente podemos actualizar text.fontsize. Es una buena práctica
escribir esto antes de hacer parcelas y definir el valor que más le convenga. Si luego desea cambiar el tamaño de fuente para
algún atributo de la trama, puede definir ese valor en particular allí. Usaremos estos tamaños de fuente en todos los gráficos
de ahora en adelante, pero no agregaremos este texto en cada código por razones de brevedad.

7.1 Eje de fecha

La mayoría de los datos en hidrología son datos de series temporales. Para graficar dichos datos, se requiere que el eje x
sea el eje del tiempo, y que los datos se grafiquen en el eje y. Usaremos la biblioteca de series temporales del paquete scikits
para manejar datos de series temporales, que también proporciona funciones para trazar datos de series temporales.
Generaremos algunos datos a intervalos regulares (diarios), que es como tener datos simulados usando algún modelo, y
algunos datos en tiempo aleatorio, que es como tener mediciones en intervalos irregulares. Los datos de medición también
contienen vectores correspondientes para el tiempo, es decir, año, mes y día.
Machine Translated by Google

82 Capítulo 7. Trazado

>>> importar scikits.timeseries como ts >>> x =


np.arange(500) >>> y_sim = np.sin(x/25.0) >>> año
= [2009, 2010, 2010, 2010, 2011] # año para la
medición # mes para la medición >>> mes = [10, 2, 5, 9, 1] >>> día = [20, 15, 17, 22, 15] # día
para la medición >>> y_meas = [0.4 , -0.5, 0, 1, 0]

Comenzamos con la creación de la serie de tiempo para datos regulares. Para hacerlo, primero definimos la fecha de inicio, luego
usamos esta fecha de inicio y los datos simulados para crear un objeto de series temporales usando ts.timeseries.

>>> primera_fecha = ts.Date(freq='D',year=2009,month=10,day=05) >>> data_series =


ts.time_series(y_sim, start_date=first_date)

Como los datos medidos no tienen una frecuencia regular, no podemos definirlos tan fácilmente. Necesitamos hacer objetos
de fecha para cada fecha, y luego podemos crear objetos de serie de tiempo.

>>> fecha = [] >>>


for i in range(largo(año)):
>>> fecha.append(fechahora.fecha(año[i], mes[i], día[i])) >>> meas_series =
ts.time_series(y_meas, fechas=fecha,frecuencia='D')

scikits.timeseries proporciona lib.plotlib para hacer gráficos de series de tiempo. La biblioteca tiene funciones
similares para hacer gráficos y, por lo tanto, es fácil de adoptar. La Fig. 7.1 muestra el gráfico con eje de tiempo.

>>> importar scikits.timeseries.lib.plotlib como tpl >>> fig = tpl.tsfigure()


>>> fsp = fig.add_tsplot(111) >>> fsp.tsplot(data_series, 'r', lw=3 ,
etiqueta='simulado') >>> fsp.tsplot(medida_serie, 'g*', ms=20,
etiqueta='medido') >>> fsp.set_ylim(-2, 2) >>> fsp.grid( ) >>> plt.ylabel('Datos') >>>
fsp.legend(loc='mejor') >>> plt.savefig('/home/tomer/my_books/python_in_hydrology/
images/date.png') > >> plt.cerrar()

7.2 Gráficos de barras

Primero vamos a crear algunos datos. Crearemos dos variables (lluvia y escorrentía) de longitud 5.

>>> import numpy as np >>>


import matplotlib.pyplot as plt >>> n = 5 >>>
rain_mean = 500+300*np.random.rand(n) >>>
runoff_mean = 0.75*np.random. rand(n)*promedio_de_lluvia

La barra requiere el valor correspondiente para x y no se calcula por sí misma. También estamos especificando el
ancho de las barras. plt.bar devuelve parches rectangulares que se pueden usar para modificar
Machine Translated by Google

7.3. Gráficos circulares 83

Figura 7.1: Gráfico que muestra fechas para el eje x.

parches o para extraer alguna información de ellos. En este ejemplo, estos parches rectangulares se usan para extraer
su altura y luego colocar texto en la parte superior de las barras. La Fig. 7.2 muestra el diagrama de barras.

>>> ind = np.arange(n) # las ubicaciones x para los grupos >>> ancho = 0.35
# el ancho de las barras
>>>
>>> rects1 = plt.bar(ind, precipitación_media, ancho, color='g', etiqueta='Lluvia') >>> rects2 = plt.bar(ind+ancho,
runoff_mean, ancho, color='m', etiqueta = 'Escorrentía')
>>>
>>> plt.ylabel('Suma anual (mm)') >>>
plt.title('Balance hídrico') >>> plt.xticks(ind+ancho,
('2001', '2002', '2003' , '2004', '2005') )
>>>
>>> def autoetiqueta(rects):
>>> # adjunte algunas etiquetas de texto
>>> para rect in rects:
>>> altura = rect.get_height()
>>> plt.text(rect.get_x()+rect.get_width()/2., 1.05*height, '%d'%int(height),
>>> ha='centro', va='abajo')
>>>
>>> plt.leyenda() >>>
autolabel(rects1) >>>
autolabel(rects2)
>>>
>>> plt.ylim(ymax=1000) >>>
plt.savefig('/home/tomer/my_books/python_in_hydrology/images/bar.png') >>> plt.close()

7.3 Gráficos circulares

Primero generamos tres variables, escorrentía, recarga y evapotranspiración asumiendo algo de lluvia.
Machine Translated by Google

84 Capítulo 7. Trazado

Figura 7.2: Gráfico que muestra un ejemplo de barra.

>>> lluvia = 1000


>>> escorrentía = 0.5*np.random.uniform()*lluvia >>> recarga =
0.2*np.random.uniform()*lluvia >>> evapotranspiración = lluvia -
escorrentía - recarga

Modificamos el tamaño de la figura por su tamaño predeterminado para hacer que la trama sea cuadrada. Luego, definimos el área
para el gráfico circular especificando el plt.axis.

>>> plt.figura(tamañofig=(8,8)) >>>


plt.eje([0.2, 0.2, 0.8, 0.8])

Hacemos una lista de las variables y una tupla para el nombre de las variables.

>>> etiquetas = 'Escorrentía', 'Recarga', 'Evapotranspiración' >>> fracs =


[escorrentía, recarga, evapotranspiración]

Podemos usar explotar para resaltar alguna de las variables, en este caso 'Recargar'. La cantidad de explosión está
controlada por sus parámetros. El autopct se usa para definir el formato del número dentro del pastel. La figura 7.3
muestra el gráfico circular.

>>> explotar=(0, 0.1, 0) >>>


plt.pie(fracs, explotar=explotar, etiquetas=etiquetas, autopct='%1.1f%%', sombra=Verdadero) >>> plt.titulo( 'Balance
hídrico anual', bbox={'facecolor':'0.6', 'pad':10}) >>> plt.savefig('/home/tomer/my_books/python_in_hydrology/images/
pie.png')

7.4 Parcelas 2D
Las imágenes (JPEG, TIFF, PNG, etc.) vienen en dos formatos: escala de grises o RGB. plt.imshow se puede utilizar
para mostrar ambos tipos de imágenes. Primero usamos imread para leer los datos de las figuras, luego creamos
una matriz de datos tridimensional creando primero una matriz vacía y luego especificando los datos de cada banda
en orden RGB (rojo, verde azul). Si estamos leyendo una imagen que tiene las tres bandas en una sola imagen, el
imread proporcionará los datos como una matriz tridimensional y se puede usar directamente.
Machine Translated by Google

7.4. Parcelas 2D 85

Figura 7.3: Gráfico que muestra un ejemplo de pastel con explosión.

El imshow se usa para hacer el gráfico bidimensional con el tipo de algoritmo de interpolación para cambiar su tipo de
interpolación predeterminado. La Fig. 7.7 muestra un mapa bidimensional generado usando imshow.

>>> band2 = plt.imread('/home/tomer/my_books/python_in_hydrology/datas/band2.tif') >>> band3 = plt.imread('/home/tomer/


my_books/python_in_hydrology/datas/band3.tif ') >>> band4 = plt.imread('/home/tomer/my_books/python_in_hydrology/datas/
band4.tif')
>>>
>>> foo = np.vacío((banda2.forma[0], banda2.forma[1], 3)) >>> foo[:,:,2] = banda2
>>> foo[:,:,1 ] = banda3 >>> foo[:,:,0] = banda4

>>>
>>> plt.imshow(foo, interpolation='hanning') >>> plt.savefig('/home/
tomer/my_books/python_in_hydrology/images/imshow.png')

pcolor significa pseudo color y se usa para aumentar el contraste en los datos al hacer gráficos.
La barra de colores se utiliza para mostrar el mapa de colores. El tipo de mapa de colores se controla utilizando cmap
como entrada para pcolor. La Fig. 7.5 muestra el diagrama de pseudocolor.

>>> plt.pcolor(banda2, cmap=plt.cm.Emparejado) >>>


plt.colorbar() >>> plt.ylim(ymax=banda2.forma[0]) >>>
plt.savefig('/ home/tomer/mis_libros/python_in_hydrology/images/
pcolor.png')
Machine Translated by Google

86 Capítulo 7. Trazado

Figura 7.4: Gráfico bidimensional usando el imshow.

Figura 7.5: Gráfico bidimensional usando el pcolor.

Usaremos los datos de la banda 2 para hacer los contornos. Dado que los datos de 'banda 2' tienen una variabilidad
espacial muy alta, primero los filtraremos usando el filtro mediano.

>>> de scipy.signal import medfilt2d >>> data =


medfilt2d(band2, kernel_size=7)

plt.contour se usa para hacer contornos. Por defecto no muestra los valores de contorno, para mostrar las etiquetas
de contorno, usamos el plt.clabel. La Fig. 7.6 muestra el gráfico de contorno junto con las etiquetas de contorno.

>>> CS = plt.contour(datos,10) >>>


plt.clabel(CS, en línea=1, tamaño de fuente=10) >>>
plt.savefig('/home/tomer/my_books/python_in_hydrology/images/contour .png')
Machine Translated by Google

7.4. Parcelas 2D 87

Figura 7.6: Gráfico que muestra el contorno junto con las etiquetas de contorno.

plt.contour proporciona el contorno vacío, es decir, no hay color entre los contornos sucesivos. Podemos usar contourf para
hacer diagramas de contorno llenos. La Fig. 7.7 muestra el gráfico de contorno lleno.

>>> plt.contourf(data,10) >>>


plt.colorbar() >>> plt.savefig('/home/
tomer/my_books/python_in_hydrology/images/contourf.png')

Figura 7.7: Contorno relleno trazado usando el contornof.


Machine Translated by Google

88 Capítulo 7. Trazado

7.5 Gráficos 3D

Para hacer un gráfico tridimensional, necesitamos importar la biblioteca Axes3D desde mpl_toolkits.mplot3d. El
diagrama de dispersión o línea en tres dimensiones se realiza de manera similar a dos dimensiones.
Generaremos tres variables y haremos el diagrama de dispersión tridimensional. La Fig. 7.8 muestra el gráfico
de dispersión tridimensional.

>>> importar numpy como np


>>> desde mpl_toolkits.mplot3d importar Axes3D
>>>
>>> x = np.aleatorio.randn(100) >>> y
= np.aleatorio.randn(100) >>> z =
np.aleatorio.randn(100)
>>>
>>> fig = plt.figura() >>> hacha
= fig.add_subplot(111, proyección='3d') >>> hacha.dispersión(x,
y, z, color='k', marcador='s ')
>>>
>>> ax.set_xlabel('x') >>>
ax.set_ylabel('y') >>>
ax.set_zlabel('z') >>>
plt.savefig('/home/tomer/my_books/python_in_hydrology/ imágenes/3dscatter.png') >>> plt.cerrar()

Figura 7.8: Eje de fecha

7.6 Diagrama de caja

El diagrama de caja es una forma de visualizar gráficamente las propiedades estadísticas de los datos.
Proporciona información sobre el mínimo, primer cuartil (Q1), mediana (Q2), cuartil superior (Q3), máximo y
Machine Translated by Google

7.7. Gráfico QQ 89

valores atípicos si están presentes. boxplot se usa para hacer boxplot. Fig. ?? muestra el diagrama de caja.

>>> n = 4
>>> x = rango(n)
>>> y = 5+np.aleatorio.randn(100,4)
>>>
>>> plt.boxplot(y,'gD') >>>
plt.savefig('/home/tomer/my_books/python_in_hydrology/images/boxplot.png')

Figura 7.9: Diagrama de caja de datos.

7.7 Gráfico QQ
La gráfica QQ (cuantil-cuantil) es un método gráfico para comparar dos distribuciones de probabilidad
trazando sus cuantiles entre sí. Usaremos la biblioteca de estadísticas para calcular los cuantiles.
Generaremos tres variables aleatorias, dos con las mismas distribuciones (normales) y una con diferente
distribución (uniforme), y compararemos su comportamiento en el gráfico QQ. La figura 7.10 muestra el
gráfico QQ. En el eje x tenemos los cuantiles de distribución normal, en el eje y estamos trazando cuantiles
de distribuciones uniforme y normal. Vemos que cuando las distribuciones son iguales, caen en la línea
1:1, de lo contrario se apartan de ella.

>>> importar estadísticas como st


>>> from scipy.interpolate import interp1d
>>>
>>> def Q(datos): F,
>>> datos1 = st.cpdf(datos, n=1000) f =
>>> interp1d(F, datos1) return f(np.linspace(0,1))
>>>
>>>
Machine Translated by Google

90 Capítulo 7. Trazado

>>> x = np.aleatorio.randn(1000) >>> y =


5*np.aleatorio.rand(1000) >>> z =
np.aleatorio.randn(1000)
>>>
>>> Qx = Q(x)
>>> Qy = Q(y)
>>> Qz = Q(z)
>>>
>>> plt.plot([-5,5] , [-5,5], 'r', lw=1.5, label='línea 1:1') >>> plt.plot(Qx, Qy, ' gd',
label='Uniform') >>> plt.plot(Qx, Qz, 'm*', label='Normal') >>> plt.axis((-5, 5, -5, 5)) >>>
plt.leyenda(loc=2) >>> plt.xlabel('Normal') >>> plt.ylabel('observado') >>> plt.savefig('/
home/tomer/my_books/python_in_hydrology/ imágenes/q_q.png')

Figura 7.10: Gráfico cuantil-cuantil.

7.8 trama
Si queremos graficar dos variables en el mismo gráfico que tienen un rango diferente (mínimo y máximo), entonces
no debemos graficarlas usando el mismo eje. Si lo hacemos, no podremos ver la variación en una variable. La figura
7.11 muestra el gráfico con dos ejes y.

>>> fig = plt.figure() >>>


plt.subplots_adjust(top=0.9, bottom=0.15,left=0.15,right=0.85) >>> ax1 = fig.add_subplot(111)

>>>
Machine Translated by Google

7.8. trama 91

>>> t = np.linspace(0,10) >>> y1


= 5*np.sin(t) >>> y2 = 10*np.cos(t)

>>>
>>> ax1.plot(t, y1, 'g', label='sin') >>>
ax1.set_xlabel('tiempo(s)')
>>>
>>> #Haz que la etiqueta del eje y y las etiquetas de marca coincidan con el color de la
línea. >>> ax1.set_ylabel('sin', color='b') >>> para tl en ax1.get_yticklabels():

>>> tl.set_color('b') >>>


ax1.set_ylim(-6,6) >>>
plt.leyenda(loc=3)
>>>
>>> ax2 = ax1.twinx() >>>
ax2.plot(t, y2, 'r', label='cos') >>> ax2.set_ylabel('cos',
color='r') >> > para tl en ax2.get_yticklabels():

>>> tl.set_color('r') >>>


ax2.set_ylim(-15,15)
>>>
>>> plt.leyenda(loc=4) >>>
plt.savefig('/home/tomer/my_books/python_in_hydrology/images/multiple_y.png')

Figura 7.11: Gráfico que muestra varios ejes y.


Machine Translated by Google

92 Capítulo 7. Trazado

7.9 Anotación
Además de trazar líneas, puntos, leyendas, etc., es posible que necesitemos incluir información adicional en el gráfico.
Esto se llama anotación. Podemos poner diferentes flechas, textos, etc. para que nuestro gráfico sea más claro. Higo.
7.12 muestra una de esas figuras que tiene pocas flechas, textos para mejorar la legibilidad del gráfico.

>>> t = np.linspace(0,10)
>>> y = 5*np.sin(t)
>>>
>>> plt.plot(t, y, lw=3, color='m')
>>> plt.xlabel('x')
>>> plt.ylabel('y')
>>> plt.anotar('cresta', xy=(np.pi/2, 5), xycoords='datos',
>>> xytext=(-20, -75), textcoords='puntos de desplazamiento',
>>> puntales de flecha=dict(estiloflecha="->")
>>> )
>>>
>>> plt.anotar('valle', xy=(1.5*np.pi, -5), xycoords='datos',
>>> xytext=(-30, 80), textcoords='puntos de desplazamiento',
>>> tamaño = 20,
>>> bbox=dict(boxstyle="redondo,pad=.5", fc="0.8"),
>>> puntales de flecha=dict(estiloflecha="->",),
>>> )
>>>
>>> plt.annotate('Anotación', xy=(8, -5), xycoords='datos',
>>> xytext=(-20, 0), textcoords='puntos de desplazamiento',
>>> bbox=dict(boxstyle="redondo", fc="verde"), tamaño de fuente=15)
>>>
>>> plt.text(3.0, 0, "Abajo", color = "w", ha="centro", va="centro", rotación=90,
>>> tamaño=15, bbox=dict(boxstyle="larrow,pad=0.3", fc="r", ec="r", lw=2))
>>>
>>> plt.text(np.pi*2, 0, "ARRIBA", color = "w", ha="centro", va="centro", rotación=90,
>>> tamaño=15, bbox=dict(boxstyle="rarrow,pad=0.3", fc="g", ec="g", lw=2))
>>>
>>> plt.savefig('/home/tomer/my_books/python_in_hydrology/images/annotate.png')

7.10 Mapa base


La biblioteca Basemap de mpl_toolkits.basemap proporciona opciones para mostrar algunas variables en
el globo, mostrando los límites (hidrológicos, políticos, etc.) en las proyecciones más utilizadas.
Utilizaremos la representación gráfica de los datos de la banda 1 con el límite de la cuenca hidrográfica de Berambadi. La figura 7.13 muestra el
datos de la banda 1 con el límite de la cuenca marcada en blanco.

>>> de mpl_toolkits.basemap importar mapa base


>>> importar gdal
>>> desde gdalconst importar *
>>>
>>> # leer los datos
Machine Translated by Google

7.10. Mapa base 93

Figura 7.12: Gráfico que muestra varias anotaciones.

>>> conjunto de datos = gdal.Open("/home/tomer/my_books/python_in_hydrology/datas/band1.tif",GA_ReadOnly) >>> band1 = conjunto de


datos.GetRasterBand(1).ReadAsArray()
>>> GT = conjunto de datos.GetGeoTransform()
>>>
>>> conjunto de datos = Ninguno
>>>
>>> # hacer la coordenada para el berambadi >>> lon =
np.linspace(GT[0]+GT[1]/2, GT[0]+GT[1]*(band1.shape[1]- 0.5), banda1.forma[1]) >>> lat = np.linspace(GT[3]+GT[5]/2,
GT[3]+GT[5]*(banda1.forma[0]-0.5 ), banda1.forma[0])
>>> Lon, Lat = np.mallagrid(lon, lat)
>>>
>>> # hacer el mapa base >>> m
= Basemap(projection='merc',llcrnrlat=11.72,urcrnrlat=11.825,\
>>> llcrnrlon=76.51,urcrnrlon=76.67,lat_ts=20,resolución=Ninguna)
>>>
>>> # dibujar paralelos y meridianos. >>>
m.drawparallels(np.arange(11.7,11.9,.05),labels=[1,0,0,0]) >>>
m.drawmeridians(np.arange(76.4,76.8,.05), etiquetas=[0,0,0,1])
>>>
>>> # leer el archivo shapefile >>> s =
m.readshapefile('/home/tomer/my_books/python_in_hydrology/datas/berambadi','berambadi'
>>> color = 'w', ancho de línea = 2.5)
>>>
>>> # calcula las coordenadas de proyección del mapa nativo de la cuadrícula de latitud/
longitud. >>> x, y = m(Lon,Lat)
>>>
>>> # datos de contorno sobre el mapa >>>
cs = m.pcolor(x,y,band1,cmap=plt.cm.jet) >>> cb = plt.colorbar(cs,
shrink=0.6, extend=' ambas cosas')
Machine Translated by Google

94 Capítulo 7. Trazado

>>>
>>> plt.title(" Banda 1") >>>
plt.savefig('/home/tomer/my_books/python_in_hydrology/images/basemap.png')

Figura 7.13: Variación espacial de la banda 1 junto con el límite de la cuenca hidrográfica de Berambadi.

7.11 Eje compartido

A menudo se requiere hacer dos o más gráficos que tengan el mismo eje (x o y o ambos). plt.subplots proporciona una
manera fácil de hacer el eje común (compartido). Primero, generaremos los datos sintéticos que tienen un rango
diferente. Luego grafica usando plt.subplots. Las otras opciones en plt.subplots son similares a plt.subplot.

>>> x1 = rango(100) >>> x2


= rango(125)
>>>
>>> y1 = np.aleatorio.aleatorio(100) >>>
y2 = 2.0*np.aleatorio.aleatorio(125) >>> y3 =
np.aleatorio.aleatorio(125) >>> y4 = 1.5*np.
aleatorio.rand(100)
>>>
>>> fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex=Verdadero, sharey=Verdadero) >>> ax1.plot(x1,y1, 'ro') >>>
ax2.plot(x2,y2, 'go') >>> ax3.plot(x2,y3, 'bs') >>> ax4.plot(x1,y4, 'mp') >>> plt. tight_layout() >>> plt.savefig('/home/tomer/
my_books/python_in_hydrology/images/shared_xy.png')
Machine Translated by Google

7.12. subtrama 95

La Fig. 7.14 muestra el gráfico resultante.

Figura 7.14: Parcelas que tienen el eje común (compartido).

7.12 Subtrama
Hasta ahora, hemos utilizado subparcelas que tienen el mismo ancho y alto. Puede surgir la situación en la que necesitemos
aumentar el tamaño de alguna subtrama. En la siguiente sección, intentaremos trazar tal en tal caso. Primero, usaremos
plt.subplot, en sí mismo para hacer una subtrama en particular.

>>> x = np.aleatorio.rand(25) >>> y =


np.arcos(x)
>>>

>>> plt.close('todos') >>>


plt.subplot(221) >>>
plt.dispersión(x,y)
>>>

>>> plt.subparcela(223) >>>


plt.dispersión(x,y)
>>>

>>> plt.subplot(122) >>>


plt.scatter(x,y) >>>
plt.tight_layout() >>> plt.savefig('/
home/tomer/my_books/python_in_hydrology/images/sub_plot1.png ')

La Fig. 7.15 muestra el gráfico resultante. El plt.tight_layout() aumenta la legibilidad de las etiquetas de ticks. Si no se utiliza
esta opción, es posible que tenga figuras con etiquetas superpuestas, etc. Esta opción evita la superposición de ejes,
títulos, etc.

Ahora, haremos este tipo de tramas secundarias usando subplot2grid.


Machine Translated by Google

96 Capítulo 7. Trazado

Figura 7.15: Parcela con tramo variable de subparcelas.

>>> fig = plt.figure() >>>


fig.subplots_adjust(wspace=0.5, hspace=0.4)
>>>
>>> ax1 = plt.subplot2grid((3, 3), (0, 0)) >>> ax2 =
plt.subplot2grid((3, 3), (0, 1), colspan=2) >>> ax3 = plt.subplot2grid((3, 3), (1,
0), colspan=2, rowspan=2) >>> ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)

>>>
>>> ax1.dispersión(10*x,y) >>>
ax2.dispersión(10*x,y) >>>
ax3.dispersión(10*x,y) >>>
ax4.dispersión(10*x, y) >>>
plt.savefig('/home/tomer/my_books/python_in_hydrology/images/sub_plot2.png')

La Fig. 7.16 muestra el gráfico resultante.


Machine Translated by Google

7.12. subtrama 97

Figura 7.16: Parcela con extensión variable de subparcelas trazadas usando subplot2grid.
Machine Translated by Google

98 Capítulo 7. Trazado
Machine Translated by Google

Capítulo 8

De entrada y salida

8.1 xls
El archivo data.xls contiene los datos de humedad del suelo estimados a partir de la plataforma AMSR-E. Puede
abrir el archivo xls y echar un vistazo a su contenido. En este archivo tenemos datos en dos hojas, Ascendente y
Descendente que corresponde a la dirección del satélite. Cada hoja contiene los datos de series temporales para
varios puntos de cuadrícula. A los datos faltantes se les asigna un número de 999.9. En esta sección, leeremos los
datos de una estación todo el tiempo, modificaremos los datos que faltan y escribiremos en otro archivo xls.
Usaremos la biblioteca xlsrd para leer datos del archivo xls y xlwt para escribir los datos en el archivo xls. El xlrd no
lee el archivo de datos xlsx, debe convertir el tipo de archivo xlsx en xls antes de leer.

>>> importar xlrd >>>


importar numpy como np

Creamos un objeto de libro pasando el nombre del archivo xls a xlrd.open_workbook. La hoja de la que necesitamos
leer los datos se especifica mediante sheet_by_name.

>>> libro = xlrd.open_workbook('/home/tomer/my_books/python_in_hydrology/datas/data.xls') >>> hoja =


libro.hoja_por_nombre('Ascendente')

El número de columnas y filas en las hojas se puede verificar usando los atributos nrows y ncols respectivamente.

>>> hoja.nrows 1100

>>> hoja.ncols
39

Las dos primeras filas de nuestra hoja son el encabezado de la tabla y la latitud y la longitud y, por lo tanto, la
longitud de los datos de la serie temporal es dos menos que el número de filas. Primero creamos una matriz vacía
para almacenar los datos, y luego leemos los datos celda por celda usando cell_value. Estaremos leyendo los datos
de la cuadrícula que tiene una latitud igual a 12.4958 y una longitud igual a 75.7484, que está en la cuarta columna
(los índices comienzan con cero).

>>> sm = np.vacío(hoja.nrows-2)
Machine Translated by Google

100 Capítulo 8. Entrada-Salida

>>> año = np.vacío(hoja.nrows-2, int)


>>> mes = np.vacío(hoja.nrows-2, int)
>>> día = np.vacío(hoja.nrows-2, int)
>>> for i in range(sm.shape[0]):
>>> sm[i] = hoja.cell_value(i+2,27)
>>> año[i] = hoja.cell_value(i+2,0)
>>> mes[i] = hoja.cell_value(i+2,1)
>>> dia[i] = hoja.valor_celda(i+2,2)

Podemos comprobar los datos de alguna variable, por ejemplo, sm.

>>> sm
matriz([ 16.6, 999.9, 15.3, ..., 17.4, 999.9, 18.2])

Podemos definir todos los datos faltantes como nan.

>>> sm[sm==999.9] = np.nan


>>> sm
matriz([ 16.6, nan, 15.3, ..., 17.4, nan, 18.2])

Ahora los datos de humedad del suelo tienen nan en lugar de 999.9 para indicar los valores que faltan. escribiremos esto
datos de humedad del suelo en un archivo xls utilizando la biblioteca xlwt. Primero abrimos un libro de trabajo, luego agregamos una hoja
por nombre usando add_sheet. Después de esto comenzamos a escribir las entradas celda por celda. Finalmente, guardamos el
hoja de trabajo usando book.save.

>>> importar xlwt


>>> libro = xlwt.Libro de trabajo()
>>> hoja = libro.add_sheet('Ascendente')
>>> hoja.escribir(0,0, 'Año')
>>> hoja.escribir(0,1, 'Mes')
>>> hoja.escribir(0,2, 'Día')
>>> hoja.escribir(0,3, 'Latitud')
>>> hoja.escribir(1,3, 'Longitud')
>>>
>>> para i en rango(len(sm)):
>>> hoja.escribir(i+2, 4, sm[i])
>>> hoja.escribir(i+2, 0, año[i])
>>> hoja.escribir(i+2, 1, mes[i])
>>> hoja.escribir(i+2, 2, día[i])
>>>
>>> libro.guardar('/home/tomer/my_books/python_in_hydrology/datas/data1.xls')

He escrito una biblioteca ambhas.xls que proporciona una forma relativamente fácil de leer y escribir xls
datos. Los datos se pueden leer de la siguiente manera.

>>> de ambhas.xls importar xlsread


>>> fname = '/home/tomer/my_books/python_in_hydrology/datas/data.xls'
>>> foo = xlsread(fname)
>>> datos = foo.get_cells('a3:a5', 'Ascendente')

Los datos en el archivo xls se escriben de la siguiente manera. Los datos que se escriben deben ser un numpy
formación.
Machine Translated by Google

8.2. Archivo de texto 101

>>> from ambhas.xls import xlswrite >>> fname = '/home/


tomer/my_books/python_in_hydrology/datas/data.xls' >>> foo = xlswrite(data, 'a3', 'Ascending') >>> foo.save(fname)

Como esta biblioteca depende del xlrd, tampoco lee el archivo de datos xlsx, y debe convertir el tipo de archivo xlsx en xls antes de
leerlo.

8.2 Archivo de texto

Algunos de los programas/herramientas toman los archivos de texto del formulario de entrada y luego escriben en archivos de texto. Si
queremos hacer un procesamiento de baño (procesar muchos archivos) usando estas herramientas, entonces necesitamos modificar
los archivos de texto de entrada y extraer la información del archivo escrito por la herramienta. En esta sección, leeremos un archivo y
luego cambiaremos algunos parámetros del archivo y luego lo escribiremos.

Antes de pasar a muchas cosas, primero leeremos el archivo de texto. La 'r' es para leer, la 'w' es para 'escribir' y la 'a' es para agregar
a un archivo existente.

>>> fname_read = '/home/tomer/my_books/python_in_hydrology/datas/Albedo.prm' >>> f_read = open(fname_read, 'r') >>> for line
in f_read:

>>> línea de impresión


>>> f_read.close()
NUM_EJECUCIONES = 1

EMPEZAR

INPUT_FILENAME = /home/tomer/data/input.hdf

NOMBRE_OBJETO = MOD_Cuadrícula_BRDF|

FIELD_NAME = Albedo_BSA_Band1

NÚMERO_BANDA = 1

SUBCONJUNTO_ESPACIAL_UL_ESQUINA = ( 13.0 75.0 )

SUBCONJUNTO_ESPACIAL_LR_ESQUINA = ( 11.0 78.0 )

RESAMPLING_TYPE = BI

SALIDA_PROYECCION_TIPO = UTM

ELLIPSOID_CODE = WGS84

UTM_ZONA = 0
Machine Translated by Google

102 Capítulo 8. Entrada-Salida

PARÁMETROS_PROYECCIÓN_SALIDA = ( 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 )

NOMBRE_ARCHIVO_SALIDA = /home/tomer/data/output.tif

SALIDA_TIPO = GEO

FINAL

Vemos que el archivo tiene muchos parámetros definidos, que serán utilizados por alguna herramienta para procesar la entrada hdf
imágenes Digamos que tenemos cuatro archivos de entrada y queremos procesarlos por lotes.

>>> fname_input = ['entrada0', 'entrada1', 'entrada2', 'entrada3']


>>> fname_output = ['salida0', 'salida1', 'salida2', 'salida3']
>>>
>>> for i in range(len(fname_input)):
>>>
>>> fname_read = '/home/tomer/my_books/python_in_hydrology/datas/Albedo.prm'
>>> f_read = abrir(fname_read, 'r')
>>>
>>> fname_write = '/home/tomer/my_books/python_in_hydrology/datas/Albedo_ii.prm'.replace('ii',str(
>>> f_write = abrir(fname_write, 'w')
>>> para línea en f_read:
>>> si 'INPUT_FILENAME' en línea:
>>> línea = línea.reemplazar('entrada',fname_entrada[i])
>>> línea de impresión
>>> si 'OUTPUT_FILENAME' en línea:
>>> línea = línea.reemplazar('salida',fname_salida[i])
>>> línea de impresión
>>> f_write.write(línea)
>>>
>>> f_escribir.cerrar()
>>>
>>> f_leer.cerrar()

8.3 NetCDF
En esta sección, leeremos un archivo NetCDF y escribiremos en el mismo formato. estoy usando el
archivo, rhum.2003.nc que se puede descargar desde http://www.unidata.ucar.edu/software/
netcdf/ejemplos/archivos.html. Usaremos la biblioteca NetCDF de Scientific.IO para leer
y escriba los datos de NetCDF, así que primero importémoslos.

>>> importar numpy como np


>>> de Scientific.IO importar NetCDF como nc

Primero, abrimos el archivo.

>>> archivo = nc.NetCDFFile('/home/tomer/my_books/python_in_hydrology/datas/rhum.2003.nc', 'r')


Machine Translated by Google

8.3. NetCDF 103

Podemos ver sus atributos usando dir.

>>> dir(archivo)
['Convenciones', 'base_date', 'cerrar', 'createDimension', 'createVariable', 'descripción', 'vaciar', 'historial', 'plataforma', 'sincronizar',
'título']

El título habla sobre el título del conjunto de datos, la descripción proporciona la descripción del contenido del archivo.

>>> archivo.titulo
'media diaria de reanálisis NMC (2003)' >>>
file.description 'Los datos provienen del reanálisis
inicializado NMC\n(4x/day). Consta de la mayoría de las variables interpoladas

Podemos mirar la dimensión de los datos.

>>> archivo.dimensiones
{'lat': 73, 'time': Ninguno, 'lon': 144, 'level': 8}

Vemos que los datos tienen cuatro dimensiones: latitud, tiempo, longitud y nivel. También se da el tamaño de cada
dimensión. Ahora, podemos mirar las variables en los datos.

>>> archivo.variables
{'lat': <objeto NetCDFVariable en 0x1d33270>, 'rhum': <objeto NetCDFVariable en 0x1d33030>, 't

Esto proporciona el nombre de las variables y una referencia de la variable a los datos. Esto significa que esto no
carga los datos en la memoria, de hecho solo proporciona una referencia en el archivo, y podemos recuperar solo
la variable que queremos. Obtendremos el valor de la variable 'rhum'. Primero hacemos la referencia a algún
nombre de variable. Luego podemos ver su unidad, tipo de datos y obtener su valor.

>>> foo = archivo.variables['nivel']


>>> foo.unidades
'%'
>>> foo.typecode 'h'

>>> ron = foo.getValue

Ahora, podemos ver la forma de la variable 'rhum'.

>>> ron.forma (365,


8, 73, 144)

La primera dimensión representa el tiempo, la segunda representa los distintos niveles de presión, la tercera
representa la latitud y la última es la longitud.

Podemos escribir el archivo de la misma manera. Primero abrimos el archivo para escribir.

>>> archivo = nc.NetCDFFile('/home/tomer/my_books/python_in_hydrology/datas/test.nc', 'w')

Luego podemos definir algunos atributos globales como título, descripción, etc.

>>> setattr(archivo, 'título', 'prueba') >>>


setattr(archivo, 'descripción', 'Archivo generado durante la prueba para escribir en NetCDF')
Machine Translated by Google

104 Capítulo 8. Entrada-Salida

Ahora, podemos crear algunas dimensiones. Necesitamos definir el nombre de la dimensión y su tamaño.

>>> archivo.createDimension('lat', 73) >>>


archivo.createDimension('lon', 144) >>>
archivo.createDimension('nivel', 8) >>>
archivo.createDimension('tiempo', 365)

Ahora, podemos guardar las variables. Primero, necesitamos definir la dimensión de la lista creada arriba.
La dimensión debe ser tupla, observe la coma después de 'lat', . Después de esto, podemos
crear una variable usando createVariable, necesitamos especificar el nombre de la variable, el formato y la dimensión.
Vemos que ha creado una variable llamada 'lat' y se refiere a ella.

>>> varDims = 'lat', >>> lat =


archivo.createVariable('lat', 'f', varDims) >>> print(archivo.variables) {'lat':
<objeto NetCDFVariable en 0x2c39078>}

Finalmente, podemos asignar nuestros datos a esta variable.

>>> lat = np.aleatorio.rand(73)

Ahora, podemos cerrar el archivo.

>>> archivo.cerrar()

8.4 Encurtido

El formato Pickle es muy rápido de leer y escribir. Pero solo es útil cuando desea guardar datos para usted mismo,
por ejemplo, escribir datos de un programa y leer los mismos datos en otro programa. Primero importamos cPicle y
lo llamamos pickle.

>>> importar cPickle como pickle

Definimos una variable, por ejemplo, una lista, primero la guardamos y luego la leemos.

>>> var = [2, 5, 8, 'foo']

Usamos pickle.dump para guardar los datos.

>>> var = [2, 5, 8, 'foo'] >>>


pickle.dump(var, open( "/home/tomer/my_books/python_in_hydrology.pkl", "wb" ) )
>>>
>>> var1 = pickle.load( open( "/home/tomer/my_books/python_in_hydrology.pkl", "rb" ) >>> print(var1) [2, 5, 8, 'foo'] )
Machine Translated by Google

Capítulo 9

Modelado Numérico

9.1 Integración
Supongamos que queremos integrar alguna función y la función no se puede integrar analíticamente, entonces
optamos por la integración numérica. Para comprobar si nuestro esquema de integración numérica funciona
correctamente o no, integramos la función para la que está disponible la solución analítica y luego comparamos
nuestra solución. Entonces, comencemos con la función de una variable. Supongamos que tenemos la función
f(x) = x para integrar sobre el límite de 0 a 10. Sabemos por las matemáticas que la respuesta es 50. Probemos
ahora métodos numéricos sobre la solución. Usaremos la biblioteca integrada de scipy. Para una función simple,
usamos la función lambad en lugar de def para definir la función. La función integra.quad realiza nuestra tarea.
Devuelve la integración y el error en la integración.

>>> de scipy importar integrar >>> y_fun =


lambda x: x >>> y,err = integrar.quad(x2,0,10)
>>> imprimir(y,err) (50.0, 5.551115123125783e-13)

Obtenemos 50.0 como respuesta, que es exactamente la solución analítica, y también dice que el error es que
la solución es muy baja. Podría ser por casualidad que obtengamos una solución precisa del esquema numérico.
Así que probemos una función más, esta vez exponencial. Integraremos f(x) = exp(ÿx) sobre 0 para
ÿ.

>>> y_func = lambda x: np.exp(-x) >>> y =


integrar.quad(y_func, 0, np.inf) >>> print(y)
(1.0000000000000002, 5.842606742906004e-11)

Vemos que la solución está muy cerca de la solución analítica (1.0). Estas funciones solo tenían la variable como
entrada, pero es posible que queramos tener parámetros adicionales en la función, por ejemplo, f(x) = exp(ÿax, y
supongamos que a = 0.5 para este ejemplo. La integración.quad proporciona opciones para proporcionar
argumento adicional también.

f = lambda x,a : np.exp(-a*x) y, err =


integrar.quad(f, 0, 1, args=(0.5,))
Machine Translated by Google

106 Capítulo 9. Modelado numérico

>>> y
0.786938680574733

9.2 ODA
Resolvamos la ecuación diferencial ordinaria, dada como:

dy
= ÿxt, dt (9.1)

con,
y0 = 10. (9.2)

Primero, podemos importar las bibliotecas requeridas.

>>> importar numpy como np


>>> desde scipy importar integrar >>> importar
matplotlib.pyplot como plt

Ahora, definimos nuestra función y el temporizador en el que queremos la solución.

>>> y1 = lambda x,t : -x*t >>> t =


np.linspace(0,10)

Ahora, podemos usar integrar.odeint para resolver la ecuación diferencial ordinaria. Luego, podemos hacer un gráfico
de la solución con respecto al tiempo.

>>> y = integrar.odeint(y1, 10, t) >>> # plot >>>


plt.plot(t,y) >>> plt.xlabel('x') >>> plt.ylabel(' y') >>>
plt.savefig('/home/tomer/my_books/
python_in_hydrology/images/ode.png')

La figura 9.2 muestra la variación de y en el tiempo.

Resolvamos un sistema de ecuaciones diferenciales ordinarias dado como,

dx
= Ax, (9.3)
dt

dónde,
ÿD1 D1 0
un = ÿ ÿ
D1 ÿD1 ÿD2 D2 (9.4)
ÿ
0 D2 ÿD3 ÿ

Comenzamos con la definición de los parámetros y la matriz A.

>>> D = [0.2, 0.1, 0.3]


>>> A = np.matriz([[D[0], -D[0], 0],
Machine Translated by Google

9.3. Estimación de parámetros 107

Figura 9.1: Variación de y en el tiempo.

>>> [D[0], -D[0]-D[1], D[1]],


>>> [0, D[2], -D[2]]])

Ahora, podemos definir nuestra función dx/dt.

>>> def dX_dt(sm, t=0): devuelve


>>> np.dot(A,sm)

Finalmente, definimos el tiempo, la condición inicial, usamos integrar.odeint para resolver y luego graficamos.

>>> t = np.linspace(0, 10, 100)


>>> X0 = np.matriz([10, 5, 20])
>>> X, infodict = integrar.odeint(dX_dt, X0, t, full_output=True)
>>>
>>> plt.plot(t,X) >>>
plt.xlabel('Tiempo') >>>
plt.ylabel('X') >>>
plt.leyenda(['X1','X2',' X3']) >>> plt.savefig('/home/
tomer/my_books/python_in_hydrology/images/ode_system.png')

9.3 Estimación de parámetros

>>> from scipy importoptimize, special >>> x =


np.arange(0,10,0.01) >>> for k in np.arange(0.5,5.5): y =
special.jv(k,x)
>>>
Machine Translated by Google

108 Capítulo 9. Modelado numérico

Figura 9.2: Variación de x en el tiempo.

>>>
>>> f = lambda x: -special.jv(k,x) >>> x_max
= optimizar.fminbound(f,0,6)
>>>
>>> plt.plot(x,y, lw=3) >>>
plt.plot([x_max], [special.jv(k,x_max)],'rs', ms=12) >>> plt. title('Diferentes
funciones de Bessel y sus máximos locales') >>> plt.savefig('/home/tomer/my_books/
python_in_hydrology/images/inverse.png') >>> plt.close()
Machine Translated by Google

9.3. Estimación de parámetros 109

Figura 9.3: Demostración del modelado inverso.


Machine Translated by Google

110 Capítulo 9. Modelado numérico


Machine Translated by Google

Capítulo 10

Estadísticas avanzadas

10.1 cópula
Las cópulas se utilizan para describir la dependencia entre variables aleatorias. Cópula significa acoplar dos CDF.
Generemos dos variables aleatorias; una con distribución normal, otra combinación de la primera y distribución
uniforme.

>>> importar numpy como np


>>> importar matplotlib.pyplot como plt >>> desde
matplotlib.ticker importar NullFormatter
>>>
>>> # datos sintéticos >>> x
= np.random.randn(1000) >>> y =
np.random.randn(1000)

Primero nos gustaría saber cómo se relacionan nuestros datos mediante el uso de diagramas de dispersión, y
también nos gustaría ver cómo es la distribución de x e y. Podemos hacer esto en tres parcelas separadas o usando
subparcelas. En el presente caso, intentaremos esto en una parcela especificando diferentes ejes para estas 3
parcelas. Comenzamos definiendo los límites del eje para nuestras tres parcelas. La entrada al eje son x e y para la
esquina inferior izquierda, el ancho y la altura del gráfico. en el siguiente ejemplo estamos especificando el eje de tal
manera que las parcelas se alineen correctamente.

>>> plt.clf() >>>


axScatter = plt.axes([0.1, 0.1, 0.5, 0.5]) >>> axHistx = plt.axes([0.1,
0.65, 0.5, 0.3]) >>> axHisty = plt.ejes([0.65, 0.1, 0.3, 0.5])

Ahora, usamos este eje para hacer gráficos.

>>> # las gráficas >>>


axScatter.scatter(x, y) >>> axHistx.hist(x)
>>> axHisty.hist(y, orientación='horizontal')

>>>
>>> # establece el límite de las gráficas de histogramas
>>> axHistx.set_xlim( axScatter.get_xlim() )
Machine Translated by Google

112 Capítulo 10. Estadísticas avanzadas

>>> axHisty.set_ylim( axScatter.get_ylim() )


>>>
>>> plt.savefig('/home/tomer/my_books/python_in_hydrology/images/copula_1.png')

La Fig. 10.1 muestra el gráfico resultante.

Figura 10.1: Diagrama de dispersión junto con histogramas marginales.

Ahora, intentemos simular un conjunto de datos usando cópula. He escrito una biblioteca, ambhas.copula para
tratar con las cópulas. Esta biblioteca tiene tres cópulas (Frank, Clayton y Gumbel). Primero importamos la
biblioteca, luego inicializamos la clase.

>>> from ambhas.copula import Copula >>>


Copula(x, y, 'frank')

Podemos obtener el valor de la tau de Kendall y el parámetro de la cópula de Frank mediante los atributos tau y
theta respectivamente.

>>> imprimir(foo.tau)
0.179797979798
>>> imprimir(foo.theta)
1.66204833984

Podemos generar el conjunto usando la cópula de Frank.

>>> x1,y1 = foo.generar_xy()

Ahora, podemos trazar los datos simulados con los datos originales.

>>> plt.dispersión(x1,y1, color='g') >>>


plt.dispersión(x,y, color='r')
Machine Translated by Google

10.2. Distribución multivariante 113

>>> plt.xlabel('x') >>>


plt.ylabel('y') >>> plt.savefig('/
home/tomer/my_books/python_in_hydrology/images/copula_2.png')

La Fig. 10.2 muestra el gráfico resultante.

Figura 10.2: Conjunto simulado junto con datos originales.

10.2 Distribución multivariada


Hasta ahora, hemos generado variables aleatorias con solo distribución univariada. En esta sección, generaremos
variables aleatorias multivariadas con distribución nominal especificando la media y la matriz de covarianza en
np.random.multivariate_normal.

>>> media = [0,5] >>>


cov = [[1,0.4],[0.4,1]] >>> datos =
np.random.multivariate_normal(media,cov,5000)

Podemos comprobar su media y covarianza.

>>> print(datos.media(eje=0)) [ 0.00814047


5.00406784] >>> print(np.corrcoef(datos.T))
[[ 1. 0.40707918] [ 0.40707918 1. ]]

Vemos que la variable aleatoria generada tenía una media y una covarianza cercanas a la entrada especificada.
Machine Translated by Google

114 Capítulo 10. Estadísticas avanzadas


Machine Translated by Google

Apéndice A

Instalar biblioteca

A.1 Mapa base


La instalación de la nueva biblioteca parece muy fácil mediante el uso de pip, pero en realidad no es cierto.
Cada biblioteca tiene su propia dependencia y la forma de obtener esa dependencia y, por lo tanto, necesita
una forma especial de instalarla. Usamos Basemap para hacer mapas. Así que vamos a instalar esta biblioteca.
Esta biblioteca está disponible para descargar desde http://sourceforge.net/projects/matplotlib/files/matplotlib-
toolkits/ . Descargue la última versión del mapa base desde este enlace web. Hay algunos archivos *.exe
destinados a instalarse en Windows. No los he cansado, si tiene una ventana, puede probarlos primero, si
funcionan por alguna razón, entonces puede descargar el archivo fuente (* .tar.gz).

Después de descargar cualquier biblioteca nueva, primero debe intentar,

>>> sudo pip install /ruta/a/*.tar.gz

si esto funciona, entonces la instalación es realmente fácil.

Ahora, descomprima/descomprima el archivo descargado *.tar.gz. Si hay un archivo setup.py en el directorio,


debe ejecutar el siguiente comando (después de ingresar a la carpeta),

>>> sudo python setup.py instalar

Si esto falla, o no hay ningún archivo, setup.py entonces, debe leer el archivo Léame o el archivo de instalación.
Al menos uno de ellos le dirá cómo instalar la biblioteca. En el caso de la biblioteca de mapas base, vemos que
se dan algunas instrucciones en la sección 'instalar' en el archivo README. Dice lo primero que necesitamos
para instalar la biblioteca geos, y dice que podemos instalar yendo al subdirectorio geos en el directorio del
mapa base y emitiendo los siguientes comandos:

>>> hacer sudo


>>> sudo hacer instalar

Ahora, la biblioteca geos está instalada, puede volver al directorio del mapa base e instalarlo emitiendo el
siguiente comando:

>>> sudo python setup.py instalar


Machine Translated by Google

Índice

futuro , 39 Gtiff, 72

Anotación, 92 histograma, 43
naranja, 22
matriz, 21 IDE, 4
manipulación de matrices, 26 imágenes, 85
Atributo, 12 indexación, 25
Autocorrelación, 63 Instalar paquetes, 2
Instalar Python, 1
barra, 31, 82
Integración, 105
Mapa base, 92
interpolación, 61
diagrama de caja, 88

Tau de Kandall, 56
FCD, 46
Estimaciones del núcleo, 47
prueba chi cuadrado,
prueba KS, 55
55 colorbar, 34
contorno, 87 contornof,
Regresión lineal, 59
34, 87 cumsum, 31
linspace, 21 loop, for, 15

tipo de datos, 7
Mac OS, 2
Distribución, Cauchy, 50
mallas, 33
Distribución, Chi, 50
Método, 12
Distribución, Exponencial, 50
Distribución, Laplace, 52
NDVI, 77
Distribución, normal, 48
índices negativos, 9
Distribución, Uniforme, 50
NetCDF, 102

ECDF, 46 Regresión no lineal, 60 np, 20

vacío, 23
Ejecutar, 4
ODE, 106
exp, 29
ogr, 75 unos,
Fedora, 2 22

Filtro, mediana, 76, 86


Filtro, Viena, 76 Estimación de parámetros, 107

Filtrado, 75 pcolor, 86

fmin, 40 PDF, 45

fminbound, 108 correlación de Pearson, 56

BSD libre, 2 encurtidos, 104

Función, 18 pastel, 83
Trama, 3D, 88
Geotransformar, 72 plt, 20
Machine Translated by Google

Índice 117

gráfico QQ, 89

rand, 23
randn, 23
Ráster, 69
Ráster, leer, 74
Ráster, escribir, 72
ravel, 28 rcparams,
81 relfreq, 44

dispersión,
34 scikits.timeseries, 81
punto y coma (;), 30
forma, 27 Shapefile, 73
correlación de Spearman,
56 instrucción, interrupción, 18
instrucción, continuar, 18
instrucción, si, 16 instrucción,
pase, 18 instrucción, mientras,
16 cadenas , 8 subtrama, 36

Prueba T, 54
archivo de texto, 101

Tipo de errores, 4

Ubuntu/Debian, 2
Paquetes de actualización, 3

vectorial, 69
Vector, leer, 75
Vector, escribir, 73

Ventanas, 2
wspace, 37, 51

xlim, 34
xls, 99

ylim, 34

ceros, 22

También podría gustarte