SlideShare una empresa de Scribd logo
Introdución al procesamiento de datosIntrodución al procesamiento de datos
Profesores:
Javier Lacasta (jlacasta@unizar.es)
F. Javier López (fjlopez@unizar.es)
Javier Zarazaga (javy@unizar.es)
Grupo de Sistemas de Información Avanzados ( )https://www.iaaa.es (https://www.iaaa.es)
Introducción: Presentación de estas Jornadas.
Tabla de contenidosTabla de contenidos
Objetivos
Contenidos y herramientas
Primeros pasos para procesar datos
ObjetivosObjetivos
¿Qué queremos hacer?
Aprender a trabajar en el sector agroalimentario aragonés con datos y portales de datos
abiertos.
¿Cómo lo queremos lograr?
Capacitando en competencias digitales basadas en el uso de datos, datos abiertos y
herramientas que mejoren la competitividad, procesos o información en el sector
agroalimentario.
ContenidosContenidos
1. Introducción al procesamiento de datos
2. Fuentes de datos
3. Introducción a Python/Jupyter
4. Carga de datos y exploración inicial
5. Limpieza y manipulación de datos
6. Análisis y visualización de datos
7. Modelos de datos
8. Visualización de datos espaciales
Recordamos los requisitosRecordamos los requisitos
Disponer de ordenador portátil con la distribución de Python 3.7 para ciencia de
datos Anaconda
Veri!car que efectivamente funciona escribiendo en un terminal:
Esta presentación está disponible en:
https://www.anaconda.com/distribution/
(https://www.anaconda.com/distribution/)
jupyter notebook
https://github.com/IAAA-Lab/curso-analisis-datos-python (https://github.com/IAAA-
Lab/curso-analisis-datos-python)
¿Qué es Anaconda?¿Qué es Anaconda?
Una distribución de código abierto de Python/R para ciencia de datos en Linux, Windows y
macOS.
Analizar datos con numpy y pandas.
Visualizar con maplotlib.
Gestor paquetes conda.
+1500 paquetes de Python/R para datos.
¿Qué es Jupyter Notebook?¿Qué es Jupyter Notebook?
Web: Un entorno web interactivo para crear Jupyter Notebooks .
Documento: Un notebook es un documento que contiene una lista ordenada de celdas
que pueden contener código, texto, diagramas.
Ejecutable: La edición es interactiva y puede ejecutar código.
Extensible: todas las sesiones las haremos sobre un notebook que al mismo tiempo
puede verse como una presentación (extensión RISE ).
Primeros pasos para procesar datosPrimeros pasos para procesar datos
1. Comprender el problema
2. Aproximarse de forma analítica al problema
3. Establecer los requisitos que deben tener los datos
4. Obtener los datos
5. Comenzar a explorarlos
Comprensión del problemaComprensión del problema
Es un paso obvio, pero con frecuencia olvidado.
Tenemos que entender las características del problema.
Aproximación analíticaAproximación analítica
¿Podemos expresar el problema como un problema que requiere de datos?
¿Podemos expresar el problema en términos de técnicas de procesamiento?
¿Conocemos las ventajas e inconvenientes de dichas técnicas?
¿Conocemos cómo implementar dichas técnicas (por ejemplo con Python)?
RequisitosRequisitos
¿Nos vale cualquier tipo de dato?
(Conocimiento del dominio) + (Técnicas) = Datos que necesitamos
Captura de datosCaptura de datos
Estructurados: un !chero CSV (hay !las y columnas)
Semi estructurados: una pagina web (hay estructura y texto)
No estructurados: un !chero PDF (no hay estructura o extracción muy difícil)
ObjetivosObjetivos
¿Qué queremos hacer?
Aprender a trabajar en el sector agroalimentario aragonés con datos y portales de datos
abiertos.
¿Cómo lo queremos lograr?
Capacitando en competencias digitales basadas en el uso de datos, datos abiertos y
herramientas que mejoren la competitividad, procesos o información en el sector
agroalimentario.
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Datos de Open Data Aragón con las solicitudes de ayudas de la PAC 2018.
In [2]: import pandas as pd
pd.set_option('display.max_columns', None)
pac = pd.read_csv(
'https://opendata.aragon.es/GA_OD_Core/download?view_id=78&filter_sql=CCOSEC%2
0%3D%272018%27&formato=csv&name=Pol%C3%ADtica%20Agraria%20Com%C3%BAn%20(PAC)%20201
8%20Arag%C3%B3n&nameRes=Solicitudes%20de%20ayudas%20PAC%202018&nameRes=Solicitudes
%20de%20ayudas%20PAC%202018',
sep=';', quotechar='"')
pac.head()
Out[2]:
CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTADO SE
0 2018 22 1 1
2018-
05-15
13:48:30
2018-
05-29
00:00:00
22 130 BERNUES 22711 1995 SO V
1 2018 22 1 2
2018-
05-10
20:17:15
2018-
05-30
00:00:00
22 130 JACA 22700 1967 CA V
2 2018 22 1 3
2018-
03-01
09:38:32
2018-
03-01
00:00:00
22 130 JACA 22700 1955 SO V
3 2018 22 1 4
2018-
03-01
12:58:16
2018-
03-01
00:00:00
22 76 BINIÉS 22773 1947 CA V
4 2018 22 1 5
2018-
03-02
11:50:53
2018-
03-02
00:00:00
22 76 BINIÉS 22773 1947 SO V
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Alternativamente, cargamos el !chero de un directorio de nuestro disco
In [3]: import pandas as pd
pd.set_option('display.max_columns', None)
pac = pd.read_csv('datos/ayudasPAC2018.csv',
sep=';', # Separados por punto y coma
quotechar='"' # Delimitados por comillas dobles
)
pac.head()
Out[3]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTAD
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Obtenemos las dimensiones del conjunto de datos
In [4]: print(pac.shape)
Así que vemos que hay 44980 !las y 15 columnas.
(44980, 14)
Siguientes pasosSiguientes pasos
Ahora habría que explorar los datos para:
Comprender su contenido
Evaluar su calidad
Descubrir cualquier información preliminar relevante
Determinar si hay que completar la información
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Veamos que información disponemos:
In [5]: # Muestra todos los valores únicos en la columna DLOCAL
print("DLOCAL contiene", pac['DLOCAL'].unique().size, "valores distintos:")
print(pac['DLOCAL'].unique())
# Muestra todos los valores únicos en la columna CESTADO
print("CESTADO contiene", pac['CESTADO'].unique().size, "valores distintos:")
print(pac['CESTADO'].unique())
¿Qué problema tiene este conjunto de datos?
Conclusión: Comprender el dato implica comprender los problemas que puede tener
DLOCAL contiene 2935 valores distintos:
['BERNUES' 'JACA' 'BINIÉS' ... 'ANENTO' 'Villadoz'
'Villar de los Navarros']
CESTADO contiene 6 valores distintos:
['SO' 'CA' 'VI' 'None' 'DI' 'SJ']
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Vamos a arreglar algunos de los problemas.
Podemos normalizar valores
Hay nombres de municipios en mayusculas y otros en minúsculas
In [6]: pac['DLOCAL'] = pac['DLOCAL'].str.lower()
print("DLOCAL contiene", pac['DLOCAL'].unique().size, "valores distintos:")
El número de localidades se reduce de 2935 a 2360 si ignoramos las mayúsculas y las
minúsculas.
DLOCAL contiene 2360 valores distintos:
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Podemos localizar casos raros
Podemos ver lon nombres que sólo pasan una vez
In [7]: unicos = pac['DLOCAL'].value_counts() == 1
valores = sorted(unicos[unicos].index.values)
print(len(valores))
valores[:10] # Devuelve los 10 primeros
Out[7]:
843
[' portellada, la ',
'192',
'22520',
'abadiño',
'abenfigo',
'abenfigo- castellote',
'ademuz',
'agramunt',
'aguatón',
'aguilar']
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Podemos modi!car los datos de forma masiva
Podemos eliminar los espacios que hay antes y después
In [8]: pac['DLOCAL'] = pac['DLOCAL'].str.strip()
unicos = pac['DLOCAL'].value_counts() == 1
valores = sorted(unicos[unicos].index.values)
len(valores)
Out[8]: 823
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Podemos modi!car los datos de forma condicionada
Podemos resolver un problema que hay con Ejea de los Caballeros
In [9]: print("Ocurrencias de 'ejea de los caballeros'",len(pac[pac['DLOCAL'].str.contains
('ejea')]))
print("Ocurrencias de la palabra 'caballeros'",len(pac[pac['DLOCAL'].str.contains(
'caballeros')]))
filtro = ~pac['DLOCAL'].str.contains('caballeros') & pac['DLOCAL'].str.contains('e
jea')
pac[filtro].head()
In [10]: pac.loc[filtro,'DLOCAL'] = 'ejea de los caballeros' #Cambia en la columna DLOCAL t
odas las filas seleccionadas a ejea de los caballeros
Out[9]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CES
24320 2018 50 6 45
08/03/2018
16:52
08/03/2018
0:00
50 95
ejea de
los c
50600 1963 VI
25248 2018 50 7 186
21/03/2018
8:56
21/03/2018
0:00
50 95 ejea 50694 1954 CA
25637 2018 50 7 576
11/04/2018
10:09
11/04/2018
0:00
50 95 ejea 50600 1942 CA
25638 2018 50 7 577
11/04/2018
10:11
11/04/2018
0:00
50 95 ejea 50600 1969 CA
25762 2018 50 7 702
25/04/2018
8:50
25/04/2018
0:00
50 95 ejea 50600 1966 VI
Ocurrencias de 'ejea de los caballeros' 614
Ocurrencias de la palabra 'caballeros' 602
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Podemos analizar valores que deben depender de otros
El código postal de Ejea de los Caballeros es 50600 .
In [11]: pac[pac['CPOSDO'] == 50600]['DLOCAL'].unique()
Out[11]: array(['ejea de los caballeros', 'san juan de mozarrifar',
'sta. anastasia', 'ejea delos caballeros', 'el sabinar',
'ejea de loscaballeros', 'zaragoza', 'bayo (el)', 'bardenas',
'valareña', 'tauste', 'pinsoro', 'farasdues', 'cariñena'],
dtype=object)
ContenidosContenidos
1. Introducción al procesamiento de datos
2. Fuentes de datos
3. Introducción a Python/Jupyter
4. Carga de datos y exploración inicial
5. Limpieza y manipulación de datos
6. Análisis y visualización de datos
7. Modelos de datos
8. Visualización de datos espaciales
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Hemos resuelto problema, ¿pero hemos descubierto algo más?
In [13]: pac[pac['CPOSDO'] == 50617]['DLOCAL'].unique()
Como DLOCAL es texto libre hay posibilidades de error en CPOSDO
Out[13]: array(['valareña', 'sabinar', 'santa anastasia', 'santa anastasi',
'el sabinar', 'sabinar (el)', 'ejea de los caballeros',
'sant anastasia', 'eje de los caballeros'], dtype=object)
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Una vez corregidos los errores, podemos guardar los datos para su uso posterior
In [14]: import csv
pac.to_csv('datos/ayudasPAC2018_Hora1.csv', sep=";", quoting = csv.QUOTE_ALL, quot
echar='"')
Primeras conclusionesPrimeras conclusiones
¿Qué hemos obtenido hasta el momento?
¿Qué ventajas supone usar una herramienta como Jupyter/Python?
Fuentes de datosFuentes de datos
Datos abiertosDatos abiertos
Son considerados datos abiertos:
Accesibles
Reutilizables
Sin exigencia de permisos especí!cos
Fuentes principalesFuentes principales
Fuentes cientí!cas
Administraciones públicas
Iniciativas de datos abiertos
Comunidades de usuarios
Fuentes de datos abiertas en EspañaFuentes de datos abiertas en España
Multitud de portales creados por los diferentes niveles administrativos en España.
También hay empresas que proporcionan de forma pública los datos que consideran
relevantes.
Ejemplos:
Portal del gobierno de España: https://datos.gob.es/
Portal del gobierno de Aragón: https://opendata.aragon.es
Catálogo de datos del Ayuntamiento Zaragoza:
https://www.zaragoza.es/sede/portal/datos-abiertos/servicio/catalogo/
Portal de ESRI España: http://opendata.esri.es/
Catálogo de la IDEE: http://www.idee.es/csw-inspire-
idee/srv/spa/catalog.search#/home
Buscando informaciónBuscando información
Catálogo de conjunto de datos navegable
Un buscador con facetas para !ltrar la información
Un API Web para automatizar las preguntas
Recordamos los requisitosRecordamos los requisitos
Disponer de ordenador portátil con la distribución de Python 3.7 para ciencia de
datos Anaconda
Veri!car que efectivamente funciona escribiendo en un terminal:
Esta presentación está disponible en:
https://www.anaconda.com/distribution/
(https://www.anaconda.com/distribution/)
jupyter notebook
https://github.com/IAAA-Lab/curso-analisis-datos-python (https://github.com/IAAA-
Lab/curso-analisis-datos-python)
Análisis de la informaciónAnálisis de la información
Descripción del conjunto de datos (titulo, descripción, categoría)
Formatos en los que está disponible: ¿Lo puedo procesar?
Productor del dato: ¿Es !able?
Extensión temporal: ¿Es del periodo de tiempo que necesito?
Extensión espacial: ¿Cubre el área espacial que necesito?
Periodicidad: Si lo necesito en el futuro ¿habrá datos?
Licencia: ¿Puedo reutilizarlo (modalidad general básica, dominio público, otras
licencias)?
Obligaciones habituales derivadas de licencias abiertasObligaciones habituales derivadas de licencias abiertas
Licencias abiertas:
Reconocimiento (CC 4.0 BY, modalidad general básica)
Compartir igual (CC 4.0 BY-SA, ODdL 1.0)
Licencias no completamente abiertas:
Sin obra derivada (CC 4.0 BY-ND)
Uso no comercial (CC 4.0 BY-NC)
Obtención del datoObtención del dato
La descarga se puede hacer directamente, o delegar en la librería de procesamiento usada.
Esto se verá en el siguiente tema.
In [1]: import requests
url = 'https://opendata.aragon.es/GA_OD_Core/download?' + 
'view_id=78&filter_sql=CCOSEC%20%3D%272018%27&formato=csv&' + 
'name=Pol%C3%ADtica%20Agraria%20Com%C3%BAn%20(PAC)%202018%20Arag%C3%B3n&' + 
'nameRes=Solicitudes%20de%20ayudas%20PAC%202018&nameRes=Solicitudes%20de%20ayu
das%20PAC%202018'
myfile = requests.get(url)
open('datos/ayudasPAC2018_Hora2.csv', 'wb').write(myfile.content)
Out[1]: 5569621
Otras fuentes de datosOtras fuentes de datos
Hay muchas otras fuentes de datos abiertos fueras de los portales.
Semi ocultas en páginas web
Sin una descripción clara de lo que contienen
En formatos no facilmente procesables
La calidad depende de la institución creadora
Colección de datos del INE.Colección de datos del INE.
Di cil identi car la información que tienen y es necesario un proceso manual para
descargarla. Al menos el formato suele ser CSV.
https://www.ine.es/dyngs/INEbase/listaoperaciones.htm
(https://www.ine.es/dyngs/INEbase/listaoperaciones.htm)
Colección de datos del Ministerio de Agricultura.Colección de datos del Ministerio de Agricultura.
Coleccion de PDFs accesibles a través de un buscador especi!co. Parte de la información
exportable a excel pero los !cheros PDF contienen información tabular que se puede usar si
no usan primero herramientas de extracción del contenido.
https://www.mapa.gob.es/es/agricultura/temas/sanidad-vegetal/productos-
!tosanitarios/registro/menu.asp (https://www.mapa.gob.es/es/agricultura/temas/sanidad-
vegetal/productos-!tosanitarios/registro/menu.asp)
Bases de datos de la Comisión EuropeaBases de datos de la Comisión Europea
Colección de TSV sobre economía, transporte, medio ambiente, energia, y comercio entre
otros a nivel europeo.
https://ec.europa.eu/eurostat/data/database (https://ec.europa.eu/eurostat/data/database)
Ejercicio de búsqueda de licenciasEjercicio de búsqueda de licencias
Buscar las licencias habituales en las fuentes de datos mostradasBuscar las licencias habituales en las fuentes de datos mostradas
Ejercicio de búsqueda de fuentes de datosEjercicio de búsqueda de fuentes de datos
Buscar fuentes de datos sobre la PAC y su licenciaBuscar fuentes de datos sobre la PAC y su licencia
Conceptos básicos de pythonConceptos básicos de python
¿Qué es Anaconda?¿Qué es Anaconda?
Una distribución de código abierto de Python/R para ciencia de datos en Linux, Windows y
macOS.
Analizar datos con numpy y pandas.
Visualizar con maplotlib.
Gestor paquetes conda.
+1500 paquetes de Python/R para datos.
De nición de variables y asignaciónDe nición de variables y asignación
Una variable es una posición de memoria del computador con un nombre al que se le puede
asignar un valor
Tipos de datos que vamos a usarTipos de datos que vamos a usar
Enteros: ... -1, 0, 1, 2 ...
Reales: -7.49, 12.9375
Booleanos: True, False
Texto: "Cualquier texto entre comillas dobles", 'o comillas simples"
De nición de una variable y asignación de un valorDe nición de una variable y asignación de un valor
nombre = 3
Ejemplo de de!nición y asignación de variablesEjemplo de de!nición y asignación de variables
In [1]: entero = 3
real = 5.1
booleano = True
texto = "Hola Mundo"
Entrada / Salida y operaciones básicasEntrada / Salida y operaciones básicas
Para poder usar las variables de!nidas necesitamos poder darles valores desde fuera del
programa y poder mostrar el su valor por pantalla. Tambien tenemos que poder manipular
su valor para calcular los resultados deseados.
Operaciones de escritura por pantallaOperaciones de escritura por pantalla
print ( variable a mostrar, segunda variable a mostrar, etc )
Operaciones básicas sobre variablesOperaciones básicas sobre variables
variable = variable + 3
variable = variable2 * variable5
variable = variable2 - variable5 / variable9 (la división se ejecuta primero)
Operaciones de lectura del tecladoOperaciones de lectura del teclado
variable = input("Texto que se le quiere mostrar al usuario")
Ejemplo de lectura, manipulación y escritura por pantallaEjemplo de lectura, manipulación y escritura por pantalla
In [2]: tempTexto = input("Dígame una temperatura en celsius: ") # Lee un numero en format
o texto
tempReal = float(tempTexto) # Convierte un texto en r
eal
tempFar = tempReal * 9/5 + 32 # Convierte los grados
print("La temperatura en Fahrenheit es", tempFar) # Muestra el resultado po
r pantalla
Dígame una temperatura en celsius: 15
La temperatura en Fahrenheit es 59.0
Resumen de conversiones de tipos de datoResumen de conversiones de tipos de dato
De real/texto a entero: int(variable)
De entero/texo a real: !oat(variable)
Cualquier cosa a texto: str(variable)
Segundo ejemplo de lectura, manipulación y escritura por pantallaSegundo ejemplo de lectura, manipulación y escritura por pantalla
In [3]: cantidad = int(input("Dígame una cantidad en pesetas: "))
print(cantidad, "pesetas son", round(cantidad / 166.386, 2), "euros") #round redon
dea un real al numero de decimales indicado
print(str(cantidad) + " pesetas son " + str(round(cantidad / 166.386, 2)) + " euro
s")
Dígame una cantidad en pesetas: 10
10 pesetas son 0.06 euros
10 pesetas son 0.06 euros
Ejercicio de lectura, manipulación y escritura por pantallaEjercicio de lectura, manipulación y escritura por pantalla
Haz un programa que convierta de metros a pies. 1 metro son 3,28084 pies.Haz un programa que convierta de metros a pies. 1 metro son 3,28084 pies.
In [4]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
CondidionesCondidiones
Permiten dividir el !ujo de ejecución entre multiples opiones.
Ejemplo de uso: En una columna numérica sustituir el valor por Negativo si es menor que
0 , Zero si es igual a 0 y Positivo al resto.
if condicion:
ejecutame si condicion es True
elif condicion_alternativa:
ejecutame si condicion es False y condicion_alterantiva True
elif otra_condicion_mas:
ejecutame si condicion y condicion_alternativa son False
y otra_condicion_mas es True
else:
si todas las condiciones son False
¿Qué es Jupyter Notebook?¿Qué es Jupyter Notebook?
Web: Un entorno web interactivo para crear Jupyter Notebooks .
Documento: Un notebook es un documento que contiene una lista ordenada de celdas
que pueden contener código, texto, diagramas.
Ejecutable: La edición es interactiva y puede ejecutar código.
Extensible: todas las sesiones las haremos sobre un notebook que al mismo tiempo
puede verse como una presentación (extensión RISE ).
Ejemplos de condicionesEjemplos de condiciones
In [5]: dia = int(input("Introduzca un dia de Enero: "))
if(dia > 31):
print("Dia no valido")
else:
print("Dia valido")
In [6]: dia = int(input("Introduzca un dia de Enero: "))
if(dia <=0 or dia > 31):
print("Dia no valido")
else:
print("Dia valido")
In [7]: dia = int(input("Introduzca un dia de Enero: "))
if(dia >=1 and dia <=31):
print("Dia valido")
else:
print("Dia no valido")
Introduzca un dia de Enero: 1
Dia valido
Introduzca un dia de Enero: 2
Dia valido
Introduzca un dia de Enero: 3
Dia valido
Ejercicio de condicionesEjercicio de condiciones
Haz un programa que lea un día de enero y diga si está en la primera quincena, en la segunda o si noHaz un programa que lea un día de enero y diga si está en la primera quincena, en la segunda o si no
es valido.es valido.
In [8]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
IteracionesIteraciones
Permiten ejecutar la misma instrucción multiples veces, cada vez con valores diferentes de
sus variables Por ejemplo: Recorrer todas las !las de una tabla de datos para calcular la
media de los valores de cada !la
for valor in rango de cualquier tipo:
ejecuto un conjunto de operaciones
valor contiene un valor en el rango
while condición igual a True:
ejecuto un conjunto de operaciones que modifican
las variables de la condición esperando
que deje en algún momento de ser True
Ejemplos de iteracionesEjemplos de iteraciones
In [9]: inicio=1; fin=10
for i in range (inicio, fin):
print(i, end = " " ) #El segundo parametro del print hace que no se cambie de
linea al mostrar por pantalla
In [10]: inicio=1; fin=10
while inicio < fin :
print(inicio, end = " " )
inicio = inicio +1
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
Ejercicio de iteracionesEjercicio de iteraciones
Haz un programa que muestre los pares mayores de 0 y menores que 20.Haz un programa que muestre los pares mayores de 0 y menores que 20.
Nota: El operador % calula el resto de la división entera. x % 2 será cero si el numero x es par.Nota: El operador % calula el resto de la división entera. x % 2 será cero si el numero x es par.
In [11]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
FuncionesFunciones
Podemos reutilizar código mediante la de!nición de funciones con def :
In [12]: def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
Calculamos el valor de fib(100) y fib(1000)
In [13]: fib(100)
fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
ListasListas
Estructura lineal que almacena multiples valores y se accede a través de un índice
In [14]: vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
print (vector)
for i in range(len(vector)):
print (i, vector[i])
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
MódulosMódulos
Una clase es una agrupación de funcionalidad para manipular datos de un tipo concreto.
Ejemplos de módulos:
Representación de una tabla para manipular su contenido
Representación de un !chero para leerlo / escribirlo
Representación de una !gura para de!nir su contenido y mostrarla por pantalla
Los módulos tiene que importarse para poder ser usados
In [15]: import random
random.randint(0,5)
Out[15]: 4
Primeros pasos para procesar datosPrimeros pasos para procesar datos
1. Comprender el problema
2. Aproximarse de forma analítica al problema
3. Establecer los requisitos que deben tener los datos
4. Obtener los datos
5. Comenzar a explorarlos
Ejemplo de uso de métodos en pandasEjemplo de uso de métodos en pandas
Los formatos soportados y como leerlos está descrito en:
Formato Lectura Escritura
csv pd.read_csv() pac.to_csv()
json pd.read_json() pac.to_json()
excel pd.read_excel() pac.to_excel()
hdf pd.read_hdf() pac.to_hdf()
sql pd.read_sql() pac.to_sql()
... ... ...
Cada operación requirere un conjunto de parametros indicado en la documentacion. Por
ejemplo:
Para leer un !chero hay que pasarle como mínimo su ruta de acceso(sea URL o nombre
!chero)
Para escribir un !chero hay que proporcionarle como mínimodonde guardarlo
https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html
(https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html)
EjemploEjemplo
In [17]: #cargamos un fichero csv indicandole el separador
pac = pd.read_csv('datos/ayudasPAC2018.csv', sep=';', quotechar='"')
#guardamos la tabla en un fichero
pac.to_csv('datos/ayudasPAC2018_Hora3.csv')
#mostramos las primeras filas por pantalla
pac.head()
Out[17]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTAD
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
Series y DataFramesSeries y DataFrames
Conceptos claves en pandas.
Serie: lista etiquetada (índices) con valores del mismo tipo
Data Frame: tabla etiquetada (nombres de columnas) compuesta de series
In [18]: for columna in pac.columns:
serie = pac[columna]
print("La columna {0} es una Serie de tamaño {1} con {2} valor(es) distinto
(s)"
.format(serie.name, len(serie.index), len(serie.unique())))
La columna CCOSEC es una Serie de tamaño 44980 con 1 valor(es) distinto(s)
La columna CPROVI es una Serie de tamaño 44980 con 3 valor(es) distinto(s)
La columna CAGENC es una Serie de tamaño 44980 con 48 valor(es) distinto(s)
La columna CCORRE es una Serie de tamaño 44980 con 2335 valor(es) distinto(s)
La columna FREGIS es una Serie de tamaño 44980 con 23987 valor(es) distinto(s)
La columna FSOLIC es una Serie de tamaño 44980 con 108 valor(es) distinto(s)
La columna CPRODO es una Serie de tamaño 44980 con 38 valor(es) distinto(s)
La columna CMUNDO es una Serie de tamaño 44980 con 314 valor(es) distinto(s)
La columna DLOCAL es una Serie de tamaño 44980 con 2935 valor(es) distinto(s)
La columna CPOSDO es una Serie de tamaño 44980 con 1427 valor(es) distinto(s)
La columna CANONAC es una Serie de tamaño 44980 con 100 valor(es) distinto(s)
La columna CESTADO es una Serie de tamaño 44980 con 6 valor(es) distinto(s)
La columna SEXO es una Serie de tamaño 44980 con 3 valor(es) distinto(s)
La columna RNUM es una Serie de tamaño 44980 con 44980 valor(es) distinto(s)
Importación y Exploración de datosImportación y Exploración de datos
Importación y Exploración de datosImportación y Exploración de datos
En esta hora se va a describir la forma de cargar / guardar datos tabulares en Python desde
diferentes formatos (.csv, .json, .xlsx etc.) y diferentes formas de visualizar su contenido
para hacernos una idea de los problemas que tienen dichos datos. En la siguiente hora se
mostrará como corregir diferentes tipos de problemas.
Tabla de contenidosTabla de contenidos
Descripción de los datos a manipular
Procesamiento de !cheros CSV (Lectura / Exploración / Escritura)
Procesamiento de !cheros en otros formatos
Descripción de los datos a manipularDescripción de los datos a manipular
Vamos a practicar la carga de un conjuntos datos en un Jupyter Notebook con la librería
Pandas de un !chero !chero CSV sobre la PAC que descargaruemos desde Open Data
Aragón.
Documentación:
Datos:
Fichero local: datos/ayudasPAC2018.csv
https://opendata.aragon.es/datos/catalogo/dataset/politica-agraria-
comun-pac-2018-aragon (https://opendata.aragon.es/datos/catalogo/dataset/politica-
agraria-comun-pac-2018-aragon)
https://opendata.aragon.es/GA_OD_Core/download?
view_id=78&!lter_sql=CCOSEC%20%3D%272018%27&formato=csv&name=Pol%C3%ADt
(https://opendata.aragon.es/GA_OD_Core/download?
view_id=78&!lter_sql=CCOSEC%20%3D%272018%27&formato=csv&name=Pol%C3%ADt
Lectura y escritura de !cheros con pandasLectura y escritura de !cheros con pandas
Los formatos soportados y como leerlos está descrito en:
Formato Lectura Escritura
csv pd.read_csv() pac.to_csv()
json pd.read_json() pac.to_json()
excel pd.read_excel() pac.to_excel()
hdf pd.read_hdf() pac.to_hdf()
sql pd.read_sql() pac.to_sql()
... ... ...
Cada operación de lectura escritura de un formato diferente tiene parametros diferentes
para ajustar la con!guración.
https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html
(https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html)
Leer CSVLeer CSV
Usamos pandas.read_csv() para leer el !chero cvs y guardarlos en un dataframe
Necesitamos como parámetros:
La localización del !chero
Indicar que los valores estan separados por ; . Se usa el parametro sep = ';'
Indicar que los valores están entre " . Se usa el parametro quotechar = '"'
Hay muchos más parametros a tener en cuenta:
La carga puede hacerse desde !cheros en la web y locales.
https://pandas.pydata.org/pandas-
docs/stable/reference/api/pandas.read_csv.html (https://pandas.pydata.org/pandas-
docs/stable/reference/api/pandas.read_csv.html)
Comprensión del problemaComprensión del problema
Es un paso obvio, pero con frecuencia olvidado.
Tenemos que entender las características del problema.
Carga de !cheros localesCarga de !cheros locales
In [2]: import pandas as pd
localizacion = 'datos/ayudasPAC2018.csv'
pac = pd.read_csv(localizacion, sep=';', quotechar='"')
print("Hecho")
Hecho
Explorar el contenidoExplorar el contenido
Independientemente del formato una vez cargado el !chero tabular, una vez cargados con
Pandas todos los !cheros se procesan igual
Visualizar la estructura de la tabla
Alteración de cabeceras
Ajuste de columnas
Generación de resumenes
Exploración básica con PandasExploración básica con Pandas
Visualizar la estructura de la tabla
Visualizar los tipos de datos de las columnas y numero de elementos
Estadisticas del contenido de las columnas
Visualización de la estructura de la tablaVisualización de la estructura de la tabla
dataframe.head(n) para ver las primeras n !las del dataframe.
dataframe.tail(n) para ver las últimas n !las del dataframe.
In [3]: pac.head(5)
Out[3]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTAD
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
Ejercicio de visualizaciónEjercicio de visualización
Muestra las últimas 3 !las del dataframe pac.Muestra las últimas 3 !las del dataframe pac.
In [4]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Visualización de tipos de datoVisualización de tipos de dato
Nos devuelve una descripción de los tipos de datos de cada columna, si hay valores y total
de !las ocupadas
dataframe.info()
In [5]: pac.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 44980 entries, 0 to 44979
Data columns (total 14 columns):
CCOSEC 44980 non-null int64
CPROVI 44980 non-null int64
CAGENC 44980 non-null int64
CCORRE 44980 non-null int64
FREGIS 44980 non-null object
FSOLIC 44980 non-null object
CPRODO 44980 non-null int64
CMUNDO 44980 non-null int64
DLOCAL 44980 non-null object
CPOSDO 44980 non-null int64
CANONAC 44980 non-null object
CESTADO 44980 non-null object
SEXO 44980 non-null object
RNUM 44980 non-null int64
dtypes: int64(8), object(6)
memory usage: 4.8+ MB
Estadisticas de las columnasEstadisticas de las columnas
Devuelve un resumen estadistico de las columnas. Si el parametro all, solo muestra las
columnas numericas.
Algunos valores tendrán el valor NaN porque no tienen sentido para el tipo de datosde
dicha columna.
Para datos númericos incluye el numero de elementos (count), media (mean), desviación
estandard (str), valor minimo y maximo (min, max) y los percentiles 25, 50 y 75
Para el resto de datos (texto y fechas), además del numero de elementos (count), el valor
mas común (top) y su frecuencia (freq). Unique indica el numero de valores distintos
dataframe.describe(include = "all")
Aproximación analíticaAproximación analítica
¿Podemos expresar el problema como un problema que requiere de datos?
¿Podemos expresar el problema en términos de técnicas de procesamiento?
¿Conocemos las ventajas e inconvenientes de dichas técnicas?
¿Conocemos cómo implementar dichas técnicas (por ejemplo con Python)?
Modi car cabecerasModi car cabeceras
Tener cabeceras no legibles di!culta la interpretación de los datos
dataframe.columns contiene las cabeceras de nuestros datos.
In [7]: print(pac.columns)
Index(['CCOSEC', 'CPROVI', 'CAGENC', 'CCORRE', 'FREGIS', 'FSOLIC', 'CPRODO',
'CMUNDO', 'DLOCAL', 'CPOSDO', 'CANONAC', 'CESTADO', 'SEXO', 'RNUM'],
dtype='object')
Como los nombres son poco útiles, vamos a crear una lista de cabeceras alternativa y
cambiar las que tenemos
In [8]: headers = ['solicitud año','solicitud código provincia','solicitud código agencia'
,'solicitud número relativo',
'solicitud registro', 'solicitud fecha','solicitante código provincia',
'solicitante código municicipio',
'solicitante localidad', 'solicitante código postal','solicitante año n
acimiento','solicitante estado civil','solicitante sexo',
'número fila']
pac.columns = headers
pac.head(5)
Out[8]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solic
e
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
Ahora podemos interpretar mejor el resumen de los datos
In [9]: pac.describe(include = "all")
Out[9]:
solicitud
año
solicitud
código
provincia
solicitud
código agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
count 44980.0 44980.000000 44980.000000 44980.000000 44980 44980 44980.000000 44980.000000 44980
unique NaN NaN NaN NaN 23987 108 NaN NaN 2935
top NaN NaN NaN NaN
14/05/2018
14:27
31/05/2018
0:00
NaN NaN ZARAGOZA
freq NaN NaN NaN NaN 11 1864 NaN NaN 2866
mean 2018.0 39.573366 23.413762 616.141574 NaN NaN 39.668831 153.193597 NaN
std 0.0 12.454863 12.361772 472.297968 NaN NaN 12.629092 132.318678 NaN
min 2018.0 22.000000 1.000000 1.000000 NaN NaN 1.000000 1.000000 NaN
25% 2018.0 22.000000 13.000000 237.000000 NaN NaN 22.000000 61.000000 NaN
50% 2018.0 44.000000 23.000000 511.000000 NaN NaN 44.000000 128.000000 NaN
75% 2018.0 50.000000 32.000000 895.000000 NaN NaN 50.000000 222.000000 NaN
max 2018.0 50.000000 48.000000 4004.000000 NaN NaN 50.000000 912.000000 NaN
Ejercicio de analisis del contenidoEjercicio de analisis del contenido
Dada la tabla de resumen de los datos identi!ca posibles problemas en losDada la tabla de resumen de los datos identi!ca posibles problemas en los
datos.datos.
Pulsa aqui para ver la solución
Analisis detallado del contenidoAnalisis detallado del contenido
El analisis general te puede dar una idea de que hay algo mal, pero hace falta un analis más
detallado de las columnas para identi!car problemas
Una buena politica de analisis es visualizar los valores distintos. El método únique del
dataframe nos permite analizar cada columna.
In [10]: print("Estados civiles", pac['solicitante estado civil'].unique())
print("Localidades", pac['solicitante localidad'].unique())
Hay muchas localidades y por defecto no se muestran todas. Si queremos mostrarlas hay
que con!gurar el entorno.
Estados civiles ['SO' 'CA' 'VI' 'None' 'DI' 'SJ']
Localidades ['BERNUES' 'JACA' 'BINIÉS' ... 'ANENTO' 'Villadoz'
'Villar de los Navarros']
Mostrar frecuencias de valoresMostrar frecuencias de valores
Cuando hay muchos valores y no se muestran todos, es interesante mostrarlos junto con el
numero de ocurrencias de cada valor.
Aquellos valores con pocas ocurrencias, es posible que sean errores.
In [11]: serie = pac['solicitante código postal'].value_counts()
serie
Out[11]: 50660 816
50600 616
22500 565
22300 533
22520 495
...
25450 1
46000 1
50110 1
3015 1
31840 1
Name: solicitante código postal, Length: 1427, dtype: int64
¿Comó sabemos cuales son las dimensiones del problema?
Contamos las veces que ocurre cada valor y mostramos un histograma
¿Cómo se distribuyen las peticiones entre localidades de menos de 100 peticiones?
In [12]: import matplotlib.pyplot as plt
plt.hist(serie, bins = 5, log = True)
Out[12]: (array([1.365e+03, 5.000e+01, 7.000e+00, 4.000e+00, 1.000e+00]),
array([ 1., 164., 327., 490., 653., 816.]),
<a list of 5 Patch objects>)
RequisitosRequisitos
¿Nos vale cualquier tipo de dato?
(Conocimiento del dominio) + (Técnicas) = Datos que necesitamos
De nición de subconjuntosDe nición de subconjuntos
Además de analizar los datos, puede ser necesario !ltrarlos para quedarnos con un
subconjunto de las !las y columnas originales
Tareas a realizar:
Filtrado de columnas
Filtrado de !las
Eliminar columnasEliminar columnas
Podemos eliminar las columnas dado su nombre. Ej: numero !la.
Operación drop: borra las columnas indicadas en el vector []
In [14]: pac2 = pac.drop(['número fila'], axis='columns')
pac2.head(3)
Observad que hemos tenido que actualizar el valor de pac .
Out[14]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solic
e
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
Ejercicio de borrado de columnasEjercicio de borrado de columnas
Borra las !las solicitud registro y solicitud fecha y muestra los primeros 5Borra las !las solicitud registro y solicitud fecha y muestra los primeros 5
resultadosresultados
In [15]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Selección y eliminación de !lasSelección y eliminación de !las
Tambien es posible seleccionar todas las !las que cumplen una condicion o eliminarlas
Se seleccionan los indices a coger y se extraen o borran
In [16]: is_jaca = pac2['solicitante localidad']=='JACA'
print (is_jaca)
0 False
1 True
2 True
3 False
4 False
...
44975 False
44976 False
44977 False
44978 False
44979 False
Name: solicitante localidad, Length: 44980, dtype: bool
In [17]: pac_jaca = pac2[is_jaca]
pac_nojaca = pac2.drop(pac2.index[is_jaca])
print("Original:", pac2.shape)
print("Jacas:", pac_jaca.shape)
print("No Jacas:", pac_nojaca.shape)
pac_jaca.head(5)
Out[17]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
sol
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
7 2018 22 1 8
07/03/2018
10:30
07/03/2018
0:00
22 130 JACA 22700 1960 SO
27 2018 22 1 28
15/03/2018
16:11
15/03/2018
0:00
22 130 JACA 22714 1966 SO
29 2018 22 1 30
15/03/2018
17:19
15/03/2018
0:00
22 130 JACA 22700 1969 SO
Original: (44980, 13)
Jacas: (85, 13)
No Jacas: (44895, 13)
Ejercicio de !ltrado de !lasEjercicio de !ltrado de !las
Crea una tabla con las personas en el CP: 28006 sin año de nacimiento en laCrea una tabla con las personas en el CP: 28006 sin año de nacimiento en la
PAC (Valor None)PAC (Valor None)
In [18]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Guardar CSVGuardar CSV
Pandas nos permite guardar los datos en formato CSV con dataframe.to_csv() .
Por ejemplo:
Pero hay más formatos y opciones:
pac.to_csv("pac-2018.csv")
import csv
pac.to_csv('datos/ayudasPAC2018_Hora4.csv', sep=";", quoting = csv.QUOTE_ALL, quo
techar='"')
Captura de datosCaptura de datos
Estructurados: un !chero CSV (hay !las y columnas)
Semi estructurados: una pagina web (hay estructura y texto)
No estructurados: un !chero PDF (no hay estructura o extracción muy difícil)
In [19]: pac.to_json('datos/pac-2018-rec_Hora4.json', orient='records')
pacjson = pd.read_json('datos/pac-2018-rec_Hora4.json', orient='records')
pacjson.head(5)
Out[19]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solic
e
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
In [20]: pac.to_html('datos/pac-2018_Hora4.html')
pachtml = pd.read_html('datos/pac-2018_Hora4.html', index_col = 0)
pachtml[0].head(5)
Out[20]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solic
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
In [21]: pac.to_excel('datos/pac-2018_Hora4.xlsx', sheet_name = "PAC2018")
pacexcel = pd.read_excel('datos/pac-2018_Hora4.xlsx', sheet_name = "PAC2018", inde
x_col = 0)
pacexcel.head(5)
Out[21]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solic
e
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
Limpieza de datosLimpieza de datos
Limpieza de datos: Procesar una colección de datos para detectar y corregir problemas de
todo tipo: valores erroneos o inexistentes, inconsistencias y formatos heterogéneos.
Tabla de contenidosTabla de contenidos
Identi!car y tratar los datos que faltan.
Estandarización.
Normalización.
Clasi!cación.
Identi car y tratar los valores que faltanIdenti car y tratar los valores que faltan
Primero preparamos los datos que preparamos en la hora anterior.
In [1]: import pandas as pd
pac = pd.read_csv('datos/ayudasPAC2018.csv', sep=';', quotechar='"')
headers = ['solicitud año','solicitud código provincia','solicitud código agencia'
,'solicitud número relativo',
'solicitud registro', 'solicitud fecha','solicitante código provincia',
'solicitante código municicipio',
'solicitante localidad', 'solicitante código postal','solicitante año n
acimiento','solicitante estado civil','solicitante sexo',
'número fila']
pac.columns = headers
pac.head(5)
Out[1]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solic
e
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
Armonizar etiquetas de los valores que faltanArmonizar etiquetas de los valores que faltan
Cuando una posición de la tabla no tiene valor, Pandas le asigna el valor " NaN "
( Not a Number ).
En nuestros datos sin embargo se usa el texto None . Usamos replace para reemplazar
todos los None por NaN para poder contarlos.
El parametro implace hace que en vez de generarse un nuevo DataFrame (tabla) la
modi!cación se haga dentro del mismo DataFrame .
In [2]: import numpy as np
pac.replace("None", np.nan, inplace = True)
Análisis de columnas en las que faltan valoresAnálisis de columnas en las que faltan valores
Una vez armonizados los valores que faltan, tenemos que analizar donde están para poder
tratarlos.
Generamos una copia del DataFrame ( datosQueFaltan ) que contenga sólo las
posiciones sin datos y las contamos.
En los resultados se puede ver que hay unos pocos problemas en fechas de solicitud y
localidad pero muchos en año nacimiento, estado civil y sexo.
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Comprobemos primero la versión de Python instalada.
Pulsemos mayúsculas+retorno para ejecutar el código de la celda.
In [1]: !python -V
Python 3.7.4
Gestionar los datos que faltanGestionar los datos que faltan
Existen dos alternativas principales, eliminación del dato o estimación de su valor:
Eliminar toda la !la o columna.
Reemplazar por la media o la más frecuente de la columna.
Reemplazar usando otra función matemática.
Posible corrección de los datos de la PAC:
Fecha, Estado civil, Sexo: reemplazar por el más frecuente.
Localidad: eliminar !las con `NaN`.
Año de nacimiento: reemplazar por la media (redondeada).
Reemplazamos el Estado civil por el más frecuente.
In [4]: valorComun = pac['solicitante estado civil'].value_counts().idxmax()
pac["solicitante estado civil"].replace(np.nan, valorComun, inplace = True)
Eliminamos las !las con NaN en la columna Fecha.
In [5]: aBorrar = pac['solicitud fecha'].isnull()
pac.drop(pac.index[aBorrar], inplace = True)
Cambiamos la Fecha de nacimiento vacía por su media.
In [6]: media = pac["solicitante año nacimiento"].astype("float").mean(axis = 0)
pac["solicitante año nacimiento"].replace(np.nan, media, inplace = True)
pac["solicitante año nacimiento"] = pac["solicitante año nacimiento"].astype("int6
4")
Ejercicio de limpieza de casillas vacíasEjercicio de limpieza de casillas vacías
Termina de limpiar los datos vacíos de las columnas que faltan y muestra queTermina de limpiar los datos vacíos de las columnas que faltan y muestra que
ya no quedan columnas por limpiarya no quedan columnas por limpiar
In [7]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
2. Estandarización2. Estandarización
El el proceso por el que se transforma los datos en un formato común que permite realizar
una comparación con sentido.
Pasar todos los nombres de municipios a minúsculas.
Quitar horas de las fechas.
Corregir nombres con errores.
Corregir correlaciones erroneas entre atributos.
...
Veamos la situación de partida.
In [8]: pac['solicitante localidad'].value_counts()
Out[8]: ZARAGOZA 2864
TAUSTE 749
HUESCA 727
EJEA DE LOS CABALLEROS 521
Zaragoza 519
...
MONREAL DEL CAMNPO 1
SANTA ENGRACIA -TAUSTE 1
MUNÉBREGA 1
Valmadrid 1
SAN MARTIN DE LA VIRGEN DE MONCAYO 1
Name: solicitante localidad, Length: 2924, dtype: int64
Pasamos todos nombres de municipios a minúsculas.
In [9]: pac['solicitante localidad']=pac['solicitante localidad'].str.lower()
pac['solicitante localidad'].value_counts()
Out[9]: zaragoza 3394
huesca 860
tauste 813
ejea de los caballeros 598
barbastro 525
...
terue 1
mora la nova 1
torre del comte 1
valderrrobres 1
aguilar 1
Name: solicitante localidad, Length: 2352, dtype: int64
Quitar horas de las fechasQuitar horas de las fechas
Convertimos las fechas en tipo datetime (día y hora) en date (día).
Podríamos hacer otras operaciones con fechas si fuera necesario, tales como seleccionar
rangos de fechas.
In [10]: pac['solicitud registro']= pd.to_datetime(pac['solicitud registro'])
print(pac['solicitud registro'][0])
pac['solicitud registro']= pac['solicitud registro'].dt.date
print(pac['solicitud registro'][0])
2018-05-15 13:48:00
2018-05-15
Corregir errores en los nombresCorregir errores en los nombres
Es recomendable revisar aquellas componentes que tienen pocas ocurrencias para ver si
están bien escritas.
El entorno de jupyter no es necesariamente el más adecuado para esta tarea.
Lo más recomendable es guardar el conteo de ocurrencias en un !chero y revisarlo
manualmente.
Los nombres se pueden corregir en la fuente original o si fuera un proceso repetible
programar los cambios en python .
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Datos de Open Data Aragón con las solicitudes de ayudas de la PAC 2018.
In [2]: import pandas as pd
pd.set_option('display.max_columns', None)
pac = pd.read_csv(
'https://opendata.aragon.es/GA_OD_Core/download?view_id=78&filter_sql=CCOSEC%2
0%3D%272018%27&formato=csv&name=Pol%C3%ADtica%20Agraria%20Com%C3%BAn%20(PAC)%20201
8%20Arag%C3%B3n&nameRes=Solicitudes%20de%20ayudas%20PAC%202018&nameRes=Solicitudes
%20de%20ayudas%20PAC%202018',
sep=';', quotechar='"')
pac.head()
Out[2]:
CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTADO SE
0 2018 22 1 1
2018-
05-15
13:48:30
2018-
05-29
00:00:00
22 130 BERNUES 22711 1995 SO V
1 2018 22 1 2
2018-
05-10
20:17:15
2018-
05-30
00:00:00
22 130 JACA 22700 1967 CA V
2 2018 22 1 3
2018-
03-01
09:38:32
2018-
03-01
00:00:00
22 130 JACA 22700 1955 SO V
3 2018 22 1 4
2018-
03-01
12:58:16
2018-
03-01
00:00:00
22 76 BINIÉS 22773 1947 CA V
4 2018 22 1 5
2018-
03-02
11:50:53
2018-
03-02
00:00:00
22 76 BINIÉS 22773 1947 SO V
Una vez localizado un nombre con error miramos sus variantes para poder corregirlas.
Solo tiene sentido hacerlo por programa si se va a tener que replicar la limpieza en el futuro
de otra fuente similar con el mismo tipo de problemas, ya que aunque es costoso crear el
programa ahorra mucho tiempo si lo tienes que hacerlo a mano muchas veces
In [12]: cp50600 = pac['solicitante código postal'] == 50600
contieneEjea = pac['solicitante localidad'].str.contains('ejea')
print(pac[cp50600]['solicitante localidad'].unique())
In [13]: pac.loc[cp50600 & contieneEjea, 'solicitante localidad'] = 'ejea de los caballero
s'
print(pac[cp50600]['solicitante localidad'].unique())
['ejea de los caballeros' 'san juan de mozarrifar' 'ejea de los c'
'sta. anastasia' 'ejea delos caballeros' 'el sabinar'
'ejea de loscaballeros' 'ejea' 'zaragoza' 'ejea de los cabaleros'
'bayo (el)' 'bardenas' 'valareña' 'ejea de los cabaleeros' 'tauste'
'pinsoro' 'farasdues' 'cariñena']
['ejea de los caballeros' 'san juan de mozarrifar' 'sta. anastasia'
'el sabinar' 'zaragoza' 'bayo (el)' 'bardenas' 'valareña' 'tauste'
'pinsoro' 'farasdues' 'cariñena']
Corregir correlaciones erróneas entre atributosCorregir correlaciones erróneas entre atributos
Hay muchos atributos en los que dado un valor del atributo el otro está determinado. Por
ejempo codigo postal y municipio. Es interesante detectar todas las situaciones en las que eso
no ocurre, ya que seguramente sean errores.
In [14]: resumen = pac.groupby('solicitante código postal')['solicitante localidad'].nuniqu
e()
for cp in resumen.loc[50800:50899].index:
if resumen.loc[cp] != 1:
filtro = pac['solicitante código postal'] == cp
print("Código {} Veces {}".format(cp, pac[filtro]['solicitante localidad']
.unique()))
In [15]: cp50840 = pac['solicitante código postal'] == 50840
pac.loc[cp50840, 'solicitante localidad'] = 'san mateo de gállego'
print(pac[cp50840]['solicitante localidad'].unique())
Código 50800 Veces ['zuera' 'zuuera' nan]
Código 50810 Veces ['ontinar de salz' 'ontinar del salz' 'zuera']
Código 50820 Veces ['san juan de mozarrifar' 'zaragoza']
Código 50830 Veces ['lomas gallego' 'villanueva de gállego' 'zaragoza'
'villanueva de gallego']
Código 50840 Veces ['san mateo de gallego' 'san mateo de gállego' 'san ateo de
gallego'
'san mateo gallego']
Código 50850 Veces ['santa eulalia de gallego' 'moran']
['san mateo de gállego']
Ejercicio de EstandarizaciónEjercicio de Estandarización
Corrige errores de estandarización de "san mateo de gallego" y de las fechas de "solicitud
fecha".
In [16]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
NormalizaciónNormalización
Es el proceso por el que se transforman valores de variables a rangos similares.
Operaciones típicas de normalización:
centrar (p.e. media = 0)
escalar (p.g. rango 0..1, o -0.5..0.5)
pac['colnum'] = pac['colnum']/pac['colnum'].max()-0.5
Vamos a cambiar el año de nacimiento por su edad.
In [17]: pac['edad'] = 2019 - pac['solicitante año nacimiento']
pac.head(5)
Out[17]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solicitan
esta
ci
0 2018 22 1 1
2018-
05-15
29/05/2018
0:00
22 130 bernues 22711 1995 SO
1 2018 22 1 2
2018-
10-05
30/05/2018
0:00
22 130 jaca 22700 1967 CA
2 2018 22 1 3
2018-
01-03
01/03/2018
0:00
22 130 jaca 22700 1955 SO
3 2018 22 1 4
2018-
01-03
01/03/2018
0:00
22 76 biniés 22773 1947 CA
4 2018 22 1 5
2018-
02-03
02/03/2018
0:00
22 76 biniés 22773 1947 SO
Reclasi caciónReclasi cación
Agrupar variables numéricas continuas en nuevas categorias por rangos de valores.
Por ejemplo, clasi!car los solicitantes en primera edad , segunda edad , tercera edad y cuarta
edad
Los valores se pueden visualizar de forma grá!ca agrupados por rangos.
In [19]: %matplotlib inline
import matplotlib as plt
from matplotlib import pyplot
plt.pyplot.hist(pac["edad"])
plt.pyplot.xlabel("edad")
plt.pyplot.ylabel("ocurrencias")
plt.pyplot.title("Agrupación por edad")
Out[19]: Text(0.5, 1.0, 'Agrupación por edad')
Si los rangos de ocurrencias son muy dispares, no se ven bien los resultados.
Esto se puede corregir usando una escala logaritmica en el eje y .
In [20]: %matplotlib inline
import matplotlib as plt
from matplotlib import pyplot
plt.pyplot.yscale("log")
plt.pyplot.hist(pac["edad"])
plt.pyplot.xlabel("edad")
plt.pyplot.ylabel("ocurrencias")
plt.pyplot.title("Agrupación por edad")
Out[20]: Text(0.5, 1.0, 'Agrupación por edad')
Ejercicio de VisualizaciónEjercicio de Visualización
Visualiza las categorias de la columna catEdadVisualiza las categorias de la columna catEdad
In [21]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Finalizamos salvando los datos limpios para utilizarlos más adelante:
In [22]: pac.to_csv('datos/ayudasPAC2018_Hora5.csv',
sep = ";",
quoting = csv.QUOTE_ALL,
quotechar = '"',
index = False)
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Alternativamente, cargamos el !chero de un directorio de nuestro disco
In [3]: import pandas as pd
pd.set_option('display.max_columns', None)
pac = pd.read_csv('datos/ayudasPAC2018.csv',
sep=';', # Separados por punto y coma
quotechar='"' # Delimitados por comillas dobles
)
pac.head()
Out[3]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTAD
0 2018 22 1 1
15/05/2018
13:48
29/05/2018
0:00
22 130 BERNUES 22711 1995 SO
1 2018 22 1 2
10/05/2018
20:17
30/05/2018
0:00
22 130 JACA 22700 1967 CA
2 2018 22 1 3
01/03/2018
9:38
01/03/2018
0:00
22 130 JACA 22700 1955 SO
3 2018 22 1 4
01/03/2018
12:58
01/03/2018
0:00
22 76 BINIÉS 22773 1947 CA
4 2018 22 1 5
02/03/2018
11:50
02/03/2018
0:00
22 76 BINIÉS 22773 1947 SO
Análisis y visualización de datos: Procesos usados para analizar el contenido de los datos y
extraer información relevante de forma analítica y visual.
Tabla de contenidosTabla de contenidos
Correlaciones y su visualización
Análisis estadístico y su visualización
Primero vamos a cargar los datos limpios de la hora anterior
In [1]: import pandas as pd
pac = pd.read_csv('datos/ayudasPAC2018_Hora5.csv', sep=';', quotechar='"')
pac.head(5)
Out[1]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solicitan
esta
ci
0 2018 22 1 1
2018-
05-15
29/05/2018
0:00
22 130 bernues 22711 1995 SO
1 2018 22 1 2
2018-
10-05
30/05/2018
0:00
22 130 jaca 22700 1967 CA
2 2018 22 1 3
2018-
01-03
01/03/2018
0:00
22 130 jaca 22700 1955 SO
3 2018 22 1 4
2018-
01-03
01/03/2018
0:00
22 76 biniés 22773 1947 CA
4 2018 22 1 5
2018-
02-03
02/03/2018
0:00
22 76 biniés 22773 1947 SO
CorrelacionesCorrelaciones
Identi car correspondencias entre conjuntos de variables numericas es importante para
determinar si hay columnas con información redundante (o para detectar que dos columnas
que deberían estar correladas no lo están).
En nuestro caso, claramente hay correlación entre la edad y el año de nacimiento y entre la
provincia y el código postal (que no sea 1.0 implica que hay errores).
La solicitud año es NaN ya que solo contiene el valor 2018 y por tanto no se puede
calcular la correlación.
In [2]: pac.corr()
Out[2]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitante
código
provincia
solicitante
código
municicipio
solicitante
código
postal
solicitante
año
nacimiento
número
la
edad
solicitud
año
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
solicitud
código
provincia
NaN 1.000000 0.534518 0.016448 0.903922 0.024093 0.904364 -0.056359 0.880337 0.056359
solicitud
código
agencia
NaN 0.534518 1.000000 -0.076022 0.479820 -0.090408 0.477984 -0.026473 0.468282 0.026473
solicitud
número
relativo
NaN 0.016448 -0.076022 1.000000 -0.002218 -0.014590 -0.002513 0.121751 0.153837 -0.121751
solicitante
código
provincia
NaN 0.903922 0.479820 -0.002218 1.000000 0.043176 0.998688 -0.049896 0.807439 0.049896
solicitante
código
municicipio
NaN 0.024093 -0.090408 -0.014590 0.043176 1.000000 0.041328 -0.002142 0.031204 0.002142
solicitante
código
postal
NaN 0.904364 0.477984 -0.002513 0.998688 0.041328 1.000000 -0.049312 0.806047 0.049312
solicitante
año
nacimiento
NaN -0.056359 -0.026473 0.121751 -0.049896 -0.002142 -0.049312 1.000000 -0.036377 -1.000000
número !la NaN 0.880337 0.468282 0.153837 0.807439 0.031204 0.806047 -0.036377 1.000000 0.036377
edad NaN 0.056359 0.026473 -0.121751 0.049896 0.002142 0.049312 -1.000000 0.036377 1.000000
Las correlaciones se pueden ver como un mapa de colores. Como es complejo, de!namos la
función heatmap para reutilizarla.
In [3]: import matplotlib.pyplot as plt
import seaborn as sns
sns.set(rc={'figure.figsize':(12,6)})
def heatmap(c):
ax = sns.heatmap(c, vmin=-1, vmax=1, center=0, cmap=sns.diverging_palette(20,
220, n=200),square=True)
ax.set_xticklabels(ax.get_xticklabels(), rotation=45,horizontalalignment='righ
t');
In [4]: %matplotlib inline
corr = pac.corr()
heatmap(corr)
Creación de indicadoresCreación de indicadores
No vemos la correlación con las etiquetas textuales y fechas ya que no son números.
Se pueden generar indicadores numéricos arti!ciales para poder obtener dichas
correlaciones si los valores son controlados.
Se crea una columna nueva por valor
In [5]: variableTemporal = pd.get_dummies(pac["solicitante sexo"])
variableTemporal.rename(columns={'M':'Hombre', 'V':'Mujer'}, inplace=True)
variableTemporal.head()
Out[5]: Hombre Mujer
0 0 1
1 0 1
2 0 1
3 0 1
4 0 1
Añadimos las nuevas columnas
In [6]: pac = pd.concat([pac, variableTemporal], axis=1)
pac.head(5)
Out[6]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
código
postal
solicitante
año
nacimiento
solicitan
esta
ci
0 2018 22 1 1
2018-
05-15
29/05/2018
0:00
22 130 bernues 22711 1995 SO
1 2018 22 1 2
2018-
10-05
30/05/2018
0:00
22 130 jaca 22700 1967 CA
2 2018 22 1 3
2018-
01-03
01/03/2018
0:00
22 130 jaca 22700 1955 SO
3 2018 22 1 4
2018-
01-03
01/03/2018
0:00
22 76 biniés 22773 1947 CA
4 2018 22 1 5
2018-
02-03
02/03/2018
0:00
22 76 biniés 22773 1947 SO
Obtención de correlacionesObtención de correlaciones
Volvemos a calcular la correlación.
In [7]: heatmap(pac.corr())
Si nos interesa conocer si los datos observados son consistentes con una correlación hay
que calcular el p-value.
Si p-value está entre 0.0 y 0.05 se considera que hay evidencia estadística de dicha
correlación.
In [8]: from scipy import stats
pearson_coef, p_value = stats.pearsonr(pac['solicitante código provincia'],
pac['solicitante código postal'])
print("El coeficiente de correlación de Pearson es {0:.8f} con un p-value de {1}"
.format(pearson_coef, p_value))
El coeficiente de correlación de Pearson es 0.99868782 con un p-value de 0.0
Ejercicio de calculo de correlacionesEjercicio de calculo de correlaciones
Calcula la correlación entre divorciados con el solicitante código postal con suCalcula la correlación entre divorciados con el solicitante código postal con su
p-valuep-value
In [9]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Obtenemos las dimensiones del conjunto de datos
In [4]: print(pac.shape)
Así que vemos que hay 44980 !las y 15 columnas.
(44980, 14)
También podemos visualizar las correlaciones entre columnas sin relación para ver su
distribución.
In [11]: sns.regplot(x="solicitud código provincia", y="edad", data=pac)
Out[11]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1e9ee910>
En este caso quizás es mejor usar un violinplot . Veamos ahora
In [12]: sns.violinplot(x="solicitud código provincia", y="edad", data=pac)
Out[12]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1dade9d0>
El análisis de correlaciones nos pueden mostrar caracteristicas tipicas en los datos.
Por ejemplo que las solicitudes de la PAC no se realizan en su mayoria en la provincia del
solitante.
In [13]: sns.violinplot(x="solicitud código provincia", y="solicitante código provincia",
data=pac)
Out[13]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1d6c21d0>
Si los valores a analizar son rangos hay herramientas de visualización más informativas.
Es mejor usar un boxplot que muestra la dispersión de los valores respecto de las
categorías.
Si analizamos el estado civil respecto de la edad que en general los agricultores de unos 50
años y los viudos pasan los 75.
In [14]: pac = pac.sort_values(by=['solicitante estado civil'])
sns.boxplot(x="solicitante estado civil", y="edad", data=pac)
Out[14]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1d7426d0>
Pero si combinamos información con otras grá!cas las conclusiones son sorprendentes
In [15]: sns.violinplot(x="solicitante estado civil", y="edad", data=pac)
Out[15]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1e393810>
Podemos combinar los pares de propiedades que nos interese visualizar, mientras el eje Y
sea numérico.
In [16]: sns.boxplot(x="solicitante sexo", y="edad", data=pac)
Out[16]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1da423d0>
Ejercicio de visualización de distribucionesEjercicio de visualización de distribuciones
Muestra la edad por estado civil del solicitante, en dos tablas por mujeres yMuestra la edad por estado civil del solicitante, en dos tablas por mujeres y
por hombrespor hombres
In [17]: #### Inicio del programa a desarrollar (listado hombres)
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
In [18]: #### Inicio del programa a desarrollar (listado mujeres)
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Siguientes pasosSiguientes pasos
Ahora habría que explorar los datos para:
Comprender su contenido
Evaluar su calidad
Descubrir cualquier información preliminar relevante
Determinar si hay que completar la información
Analisis estadístico descriptivoAnalisis estadístico descriptivo
Conteo de valores en una columna
Obtención de media y desviación
Cálculo de mínimos, máximos y cuartiles
Agrupaciones
Analisis de las características de los datosAnalisis de las características de los datos
Ya vimos en una hora anterior como sacar medidas estadisticas básicas de los datos
numéricos.
In [19]: pac.describe()
Out[19]:
solicitud
año
solicitud
código
provincia
solicitud
código agencia
solicitud
número
relativo
solicitante
código
provincia
solicitante
código
municicipio
solicitante
código postal
solicitante año
nacimiento
núm
count 44941.0 44941.000000 44941.000000 44941.000000 44941.000000 44941.000000 44941.000000 44941.000000 44941.0
mean 2018.0 39.574509 23.410516 615.720478 39.676264 153.212545 40055.464787 1958.073430 22489.9
std 0.0 12.454853 12.361782 471.941781 12.624944 132.294441 12640.013129 14.505546 12986.0
min 2018.0 22.000000 1.000000 1.000000 1.000000 1.000000 1010.000000 1835.000000 1.00000
25% 2018.0 22.000000 13.000000 237.000000 22.000000 61.000000 22550.000000 1948.000000 11242.0
50% 2018.0 44.000000 23.000000 511.000000 44.000000 128.000000 44621.000000 1958.000000 22494.0
75% 2018.0 50.000000 32.000000 894.000000 50.000000 222.000000 50341.000000 1967.000000 33734.0
max 2018.0 50.000000 48.000000 4004.000000 50.000000 912.000000 55687.000000 2014.000000 44980.0
También se puede con los datos no numéricos.
In [20]: pac.describe(include=['object'])
Out[20]: solicitud registro solicitud fecha solicitante localidad solicitante estado civil solicitante sexo catEdad
count 44941 44941 44914 44941 39997 44941
unique 106 107 2344 5 2 4
top 2018-05-14 31/05/2018 0:00 zaragoza CA V Segunda edad
freq 2119 1864 3394 29975 28224 29553
AgrupacionesAgrupaciones
Puede ser interesante obtener medias u otras medidas de subconjuntos agrupados de
columnas
In [21]: agrupacion=pac[['solicitante estado civil','edad']]
agrupacion=agrupacion.groupby(['solicitante estado civil'],as_index = False).mean
()
agrupacion.head()
Out[21]: solicitante estado civil edad
0 CA 62.054679
1 DI 55.423810
2 SJ 59.627409
3 SO 51.336640
4 VI 78.198285
Se pueden hacer agrupaciones por múltiples atributos.
Cuando hay agrupaciones de múltiples atributos es mas claro visualizarlo como tabla
agrupada ( pivot )
In [22]: agrupacion=pac[['solicitante estado civil','solicitante sexo','edad']]
agrupacion=agrupacion.groupby(['solicitante estado civil', 'solicitante sexo'],as_
index= False).mean()
pivote=agrupacion.pivot(index='solicitante estado civil',columns='solicitante sex
o')
pivote
Out[22]: edad
solicitante sexo M V
solicitante estado civil
CA 60.848381 62.889959
DI 58.414894 54.561350
SJ 60.543478 59.317212
SO 51.029590 51.381119
VI 77.734702 79.162072
La información de la agrupación también se puede mostrar como un mapa de colores (es
este caso no es muy claro)
In [23]: plt.pcolor(pivote, cmap='RdBu')
plt.colorbar()
plt.show()
Ejercicio de agrupacionesEjercicio de agrupaciones
Crea una agrupación que muestre la media de edad por provincia delCrea una agrupación que muestre la media de edad por provincia del
solicitante y sexosolicitante y sexo
In [24]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Veamos que información disponemos:
In [5]: # Muestra todos los valores únicos en la columna DLOCAL
print("DLOCAL contiene", pac['DLOCAL'].unique().size, "valores distintos:")
print(pac['DLOCAL'].unique())
# Muestra todos los valores únicos en la columna CESTADO
print("CESTADO contiene", pac['CESTADO'].unique().size, "valores distintos:")
print(pac['CESTADO'].unique())
¿Qué problema tiene este conjunto de datos?
Conclusión: Comprender el dato implica comprender los problemas que puede tener
DLOCAL contiene 2935 valores distintos:
['BERNUES' 'JACA' 'BINIÉS' ... 'ANENTO' 'Villadoz'
'Villar de los Navarros']
CESTADO contiene 6 valores distintos:
['SO' 'CA' 'VI' 'None' 'DI' 'SJ']
Modelos de predicción: Conjunto de técnicas matemáticas para crear modelos que
permitan predecir el valor de una variable en función de otras.
Tabla de contenidosTabla de contenidos
Regresión lineal
Regresión lineal multiple
Modelos no lineales
El uso de modelos de predicción implica la existencia de tres tipos de colecciones de datos:
Colección de entrenamiento: Conjunto de datos donde están de!nidos los pares de
variables independientes, variable dependiente que desearemos predecir y que se usa para
entrenar el modelo.
Colección de pruebas: Colección equivalente a la de entrenamiento. Son datos que el
modelo no ha usado al entrenarse y permite calcular la calidad en un contexto más cercano
al real.
Datos reales: Conjunto de variables independientes para las cuales no se dispone la
variable dependiente y queremos calcularla. Son el objetivo de nuestro modelo.
Colección de trabajoColección de trabajo
Para esta hora vamos a trabajar con una colección de producción de maíz en Estados
Unidos. Por tanto vamos a cargarla, analizarla y prepararla tal y como hemos visto en las
horas anteriores.
In [1]: import pandas as pd
import numpy as np
maiz = pd.read_csv('datos/prodMaizUSA.csv', sep=';')
In [2]: maiz.head(10)
Out[2]:
Año
Acres plantados
(Millones)
Acres recolectados
(Millones)
Produccion (Millones de
fanegas)
Producción por acre recolectado
(Fanegas por acre)
Precio por fanega
(dolares)
0 1926 99.66 83.28 2140.21 25.7 0.72
1 1927 98.46 83.92 2218.19 26.4 0.80
2 1928 100.40 85.83 2260.99 26.3 0.80
3 1929 99.13 83.19 2135.04 25.7 0.76
4 1930 103.92 85.53 1757.30 20.5 0.55
5 1931 109.36 91.13 2229.90 24.5 0.29
6 1932 113.02 97.21 2578.69 26.5 0.29
7 1933 109.83 92.13 2104.73 22.8 0.49
8 1934 100.56 61.25 1146.73 18.7 0.80
9 1935 99.97 82.55 2001.37 24.2 0.63
Los datos estan limpios a excepción de las cabeceras que son muy largas y los años que
salen como reales.
In [3]: cabeceras = ['año','acres plant','acres rec','producción','producción acre', 'prec
io']
maiz.columns = cabeceras
maiz['año'].astype(int)
maiz.head()
Out[3]: año acres plant acres rec producción producción acre precio
0 1926 99.66 83.28 2140.21 25.7 0.72
1 1927 98.46 83.92 2218.19 26.4 0.80
2 1928 100.40 85.83 2260.99 26.3 0.80
3 1929 99.13 83.19 2135.04 25.7 0.76
4 1930 103.92 85.53 1757.30 20.5 0.55
Observamos las correlaciones entre columnas.
In [4]: maiz.corr()
Out[4]: año acres plant acres rec producción producción acre precio
año 1.000000 -0.409857 -0.161847 0.943515 0.975485 0.800730
acres plant -0.409857 1.000000 0.904342 -0.151488 -0.337265 -0.089667
acres rec -0.161847 0.904342 1.000000 0.112375 -0.082410 0.105670
producción 0.943515 -0.151488 0.112375 1.000000 0.976388 0.788431
producción acre 0.975485 -0.337265 -0.082410 0.976388 1.000000 0.741430
precio 0.800730 -0.089667 0.105670 0.788431 0.741430 1.000000
Hay correlación entre el año y la producción y entre la producción y el precio.
No parece haber mucha correlacion entre los acres plantados
In [5]: import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
corr = maiz.corr()
ax = sns.heatmap(corr, vmin=-1, vmax=1, center=0,cmap=sns.diverging_palette(20, 22
0, n=200),square=True)
ax.set_xticklabels(ax.get_xticklabels(),rotation=45,horizontalalignment='right');
Vamos a analizar los p-value de las columnas con correlación para ver si la correlación es
signi!cativa
In [6]: from scipy import stats
res = stats.pearsonr(maiz['producción'], maiz['precio'])
print("Producción-Precio Pearson es {0:.6f} con un P-value de = {1:.2f}".format(*r
es))
res = stats.pearsonr(maiz['producción acre'], maiz['precio'])
print("ProducciónAcre-Precio Pearson es {0:.6f} con un P-value de = {1:.2f}".forma
t(*res))
res = stats.pearsonr(maiz['año'], maiz['precio'])
print("Año-Precio Pearson es {0:.6f} con un P-value de = {1:.2f}".format(*res))
Producción-Precio Pearson es 0.788431 con un P-value de = 0.00
ProducciónAcre-Precio Pearson es 0.741430 con un P-value de = 0.00
Año-Precio Pearson es 0.800730 con un P-value de = 0.00
Regresión linealRegresión lineal
La regresión lineal es un metodo que a partir de una colección de datos, nos permite deducir
la relación entre dos variables.
Dicha relación se expresa mediante una ecuación lineal.
En esta ecuación X es el predictor (variable independiente), Y es la predicción (variable
dependiente), y a y b son los parámetros lineales que permiten predecir el resultado.
Ŵ ŶƂ  Ŷ ŷų
Para elegir qué variable es más apropiada para construir un modelo de regresión lineal
podemos observar gra!camente la relación entre los pares de variables.
In [7]: maiz.plot.scatter(x='producción', y='precio')
Out[7]: matplotlib.axes._subplots.AxesSubplot at 0x1ca6dc56348
In [8]: maiz.plot.scatter(x='producción acre', y='precio')
Out[8]: matplotlib.axes._subplots.AxesSubplot at 0x1ca6ec93208
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Vamos a arreglar algunos de los problemas.
Podemos normalizar valores
Hay nombres de municipios en mayusculas y otros en minúsculas
In [6]: pac['DLOCAL'] = pac['DLOCAL'].str.lower()
print(DLOCAL contiene, pac['DLOCAL'].unique().size, valores distintos:)
El número de localidades se reduce de 2935 a 2360 si ignoramos las mayúsculas y las
minúsculas.
DLOCAL contiene 2360 valores distintos:
A la hora de realizar la predicción, necesitamos calcular una medida que nos indique lo bien
o mal que está hecha la predicción.
Las dos mas habituales son el Coe!ciente de determinación R-Cuadrado y el Error
Cuadrático Medio.
El R-Cuadrado indica la proporción de la varianza total de la variable explicada por la
regresión. Es decir la parte de la información capturada por la regresión (más alto mejor).
El error cuadrático medio mide la diferencia entre el valor actual y el predecido (más
pequeño mejor).
Para de!nir una regresion creamos el modelo y lo ajustamos ( fit ) con la propiedad
explicativa y la propiedad de respuesta.
Una vez hecha la predicción podemos comprobar su R-cuadrado y su error cuadratico
Medio
In [10]: from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
lm = LinearRegression()
X = maiz[['producción acre']]
Y = maiz['precio']
lm.fit(X,Y)
Yhat=lm.predict(X)
print(Yhat[0:5])
print(Y[0:5].array)
print(R-Cuadrado,lm.score(X, Y))
print(Error cuadratico medio, mean_squared_error(Yhat, Y))
[0.79089373 0.80472425 0.80274846 0.79089373 0.68815276]
PandasArray
[0.72, 0.8, 0.8, 0.76, 0.55]
Length: 5, dtype: float64
R-Cuadrado 0.5497178111755494
Error cuadratico medio 0.6738019115783881
Podemos obtener los parametros de la función lineal
In [11]: print(a:,lm.intercept_)
print(b:,lm.coef_)
a: 0.2831162284334352
b: [0.01975788]
Podemos visualizar los datos originales con los predichos para ver como se ajusta la
predicción
In [12]: plt.plot(X, Y, 'o', color='blue');
plt.plot(X, Yhat, 'o', color='red');
Asi pues el precio se puede aproximar a: 0.28 + 0.019*produccion acre
Se puede visualizar la linea de la regresión superpuesta con los datos y con indicadores de
varianza de los datos usando regplot .
In [13]: sns.regplot(maiz['producción acre'], maiz['precio'],data=maiz)
Out[13]: matplotlib.axes._subplots.AxesSubplot at 0x1ca6f186e88
También podemos visualizar la diferencia entre la predicción y el valor real para identi!car
si el modelo lineal nos sirve como predictor con residplot .
In [14]: sns.residplot(maiz['producción acre'], maiz['precio'])
Out[14]: matplotlib.axes._subplots.AxesSubplot at 0x1ca6f200a88
Ejercicio de regresión linealEjercicio de regresión lineal
Calcula un modelo de regresión lineal en función del año y obten su errorCalcula un modelo de regresión lineal en función del año y obten su error
cuadraticocuadratico
Calcula un modelo de regresión lineal en función de la producción y obten suCalcula un modelo de regresión lineal en función de la producción y obten su
error cuadraticoerror cuadratico
¿Cuál es el mejor estimador y cuales son sus parametros?¿Cuál es el mejor estimador y cuales son sus parametros?
In [ ]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Regresión lineal multipleRegresión lineal multiple
Puede que una sola de las columna de los no sea su!ciente para predecir el precio. Podemos
de!nir un modelo que conbine linealmente toda la información para obtener una predicción
mejor
Ŵ ŶƂ  Ŷ ŷų ŷų ŷų ŷų
In [15]: Z = maiz[['producción acre', 'año']]
lm = LinearRegression()
lm.fit(Z, maiz['precio'])
Yhat= lm.predict(Z)
print(R-Cuadrado,lm.score(Z, Y))
print(Error cuadratico medio año, mean_squared_error(Y, Yhat))
print(a:,lm.intercept_)
print(b:,lm.coef_)
R-Cuadrado 0.6736628430623427
Error cuadratico medio año 0.4883306637948677
a: -144.72542454604985
b: [-0.02182851 0.07532843]
Si visualizamos la predicción comparada con los valores originales
In [16]: plt.plot(X, Y, 'o', color='blue');
plt.plot(X, Yhat, 'o', color='red');
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Podemos localizar casos raros
Podemos ver lon nombres que sólo pasan una vez
In [7]: unicos = pac['DLOCAL'].value_counts() == 1
valores = sorted(unicos[unicos].index.values)
print(len(valores))
valores[:10] # Devuelve los 10 primeros
Out[7]:
843
[' portellada, la ',
'192',
'22520',
'abadiño',
'abenfigo',
'abenfigo- castellote',
'ademuz',
'agramunt',
'aguatón',
'aguilar']
Ejercicio de regresión lineal multipleEjercicio de regresión lineal multiple
Crea un modelo de regresión lineal multiple que utilice como entrada laCrea un modelo de regresión lineal multiple que utilice como entrada la
producción, la producción por acre recolectado y el año para calcular el precio.producción, la producción por acre recolectado y el año para calcular el precio.
Muestra gra!camente la comparativa del resultado con los datos originales.Muestra gra!camente la comparativa del resultado con los datos originales.
In [ ]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Modelos no linealesModelos no lineales
Igual que existen modelos de regresión lineales hay modelos que usan ecuaciones
polinómicas. El problema de estos modelos es identi!car el polinómio más adecuado para
ajustar los datos.
Las redes neuronales son otra alternativa para de!nir modelos de ajuste no lineales. Son
complicadas de con!gurar, ya que tienen muchos hiperparametros (neuronas, capas,
algorimo de optimización, ecuación de calculo del error, etc). Sin embargo, con datos de
entrenamiento su!cientes generan muy buenos resultados.
In [ ]: #import sys
#!conda install --yes --prefix {sys.prefix} keras
La sigiente red toma como entrada todas las columnas de la tabla menos el precio y las usa
para aprender a predecir el precio.
Tiene 2 capas: una entrada 10 neuronas conectadas con las entradas, y una salida de 1
neurona que predice el precio.
In [18]: import warnings
warnings.filterwarnings('ignore') # Desactivamos warnings en Jupyter
import tensorflow as tf
tf.get_logger().setLevel('ERROR') # Desactivamos warnings en TensorFlow
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import Adam
import numpy as np
dataset = maiz[['año','acres plant','acres rec','producción','producción acre', 'p
recio']].to_numpy()
np.random.seed(10)
np.random.shuffle(dataset)
X = dataset[:,0:5]
Y = dataset[:,5:6]
model = Sequential()
model.add(Dense(10, kernel_initializer='normal', input_shape=(5,), activation='re
lu'))
model.add(Dense(1, activation='linear'))
model.compile(optimizer=Adam(lr=0.001), loss='mean_squared_error')
model.fit(X, Y, epochs=10001, verbose=0)
Out[18]:
Using TensorFlow backend.
keras.callbacks.History at 0x1ca75cf9908
Una vez entrenado el modelo, podemos hacer predicciones con el. Comparamos los valores
con el error cuadrático medio y la diferencia entre las distribuciones.
In [19]: prediction = model.predict(X)
print(mean_squared_error(prediction, Y))
ax1 = sns.distplot(Y, hist=False, color=r, label=Valor Real)
sns.distplot(prediction, hist=False, color=b, label=Valor Estimado , ax=ax1)
plt.title('Valor real vs estimado')
plt.xlabel('Precio')
plt.ylabel('Proporción de años')
Out[19]:
0.3814094695648771
Text(0, 0.5, 'Proporción de años')
Visualización espacial de datosVisualización espacial de datos
Visualización espacial de datos: Procesos usados para la creación de mapas con diversos
objetivos.
Tabla de contenidosTabla de contenidos
Introducción a Folium
Mapas con marcadores
GeoJSON y Folium
Coropletas con Folium
Conclusión de las Jornadas
Introducción a FoliumIntroducción a Folium
Folium es una librería de Python que ayuda a crear mapas con Lea et.
Los mapas creados pueden verse embebidos en el notebook, pero se pueden exportar para
ser embebidos en páginas web.
Folium soporta OpenStreetMap, Mapbox, Statmen, GeoJSON, TopoJSON, ...
In [1]: #!conda install -c conda-forge folium
import folium
Un mapa mundial en FoliumUn mapa mundial en Folium
Es bastante trivial
In [2]: folium.Map()
Out[2]:
+
−
Leaflet (https://leafletjs.com) | Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
Ahora un mapa más interesanteAhora un mapa más interesante
In [3]: folium.Map(location=[41.6523, -0.8940], zoom_start=18)
Out[3]:
++
−
Leaflet (https://leafletjs.com) | Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Podemos modi!car los datos de forma masiva
Podemos eliminar los espacios que hay antes y después
In [8]: pac['DLOCAL'] = pac['DLOCAL'].str.strip()
unicos = pac['DLOCAL'].value_counts() == 1
valores = sorted(unicos[unicos].index.values)
len(valores)
Out[8]: 823
Pulsa aqui para ver la solución
Con gurar estilo de visualizaciónCon gurar estilo de visualización
Folium puede generar mapas con diferentes estilos además de OpenStreetMap.
Stamen Toner es un estilo de mapa de alto contraste mientras que Stamen Terrain es más
realista.
In [5]: folium.Map(location=[41.6563,-0.8811],
zoom_start=8,
tiles='Stamen Toner')
Out[5]:
++
−
Leaflet (https://leafletjs.com) | Map tiles by Stamen Design (http://stamen.com), under CC BY 3.0 (http://creativecommons.org/licenses/by/3.0). Data
by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
In [6]: folium.Map(location=[41.6563,-0.8811],
zoom_start=8,
tiles='Stamen Terrain')
Out[6]:
++
−
Leaflet (https://leafletjs.com) | Map tiles by Stamen Design (http://stamen.com), under CC BY 3.0 (http://creativecommons.org/licenses/by/3.0). Data
by © OpenStreetMap (http://openstreetmap.org), under CC BY SA (http://creativecommons.org/licenses/by-sa/3.0).
Mapas con marcadoresMapas con marcadores
Vamos a crear un mapa que muestre las localidades de zaragoza
In [7]: import pandas as pd
entidades = pd.read_csv('datos/entidades.csv', sep=';', decimal=',')
entidades.columns = ['Provincia', 'Comarca', 'Clasificación', 'Código INE', 'Denom
inación',
'Longitud', 'Latitud']
nucleos_zgz = entidades[(entidades['Provincia'] == 'Zaragoza') 
(entidades['Clasificación'] == '3.- Núcleo')]
nucleos_zgz.shape
Ahora en entidades_zgz tenemos 436 núcleos de población.
Out[7]: (436, 7)
Procedemos a crear un mapa y visualizarlo
In [8]: zaragoza = folium.Map(location=[41.6563,
-0.8811],
zoom_start=7)
localidades = folium.map.FeatureGroup()
for lat, lng, in zip(nucleos_zgz.Latitud,
nucleos_zgz.Longitud):
localidades.add_child(
folium.CircleMarker(
[lat, lng],
radius=5,
color='yellow',
fill=True,
fill_color='blue',
fill_opacity=0.6)
)
In [9]: zaragoza.add_child(localidades)
Out[9]:
++
−
Leaflet (https://leafletjs.com) | Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
Pero si queremos etiquetas usaremos marcadores
In [10]: zaragoza = folium.Map(location=[41.6563,
-0.8811],
zoom_start=7)
tupla = zip(nucleos_zgz.Latitud,
nucleos_zgz.Longitud,
nucleos_zgz.Denominación)
for lat, lng, label in tupla:
folium.Marker(
[lat, lng],
popup=label).add_to(zaragoza)
In [11]: zaragoza
Out[11]:
++
−
Leaflet (https://leafletjs.com) | Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
Pero todavía vemos que hay demasiada información, necesitamos clusters
In [12]: from folium import plugins
zaragoza = folium.Map(location=[41.6563,
-0.8811],
zoom_start=7)
zaragoza_cluster = plugins. 
MarkerCluster().add_to(zaragoza)
tupla = zip(nucleos_zgz.Latitud,
nucleos_zgz.Longitud,
nucleos_zgz.Denominación)
for lat, lng, label in tupla:
folium.Marker([lat, lng],
icon=None,
popup=label). 
add_to(zaragoza_cluster)
Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018
Podemos modi!car los datos de forma condicionada
Podemos resolver un problema que hay con Ejea de los Caballeros
In [9]: print(Ocurrencias de 'ejea de los caballeros',len(pac[pac['DLOCAL'].str.contains
('ejea')]))
print(Ocurrencias de la palabra 'caballeros',len(pac[pac['DLOCAL'].str.contains(
'caballeros')]))
filtro = ~pac['DLOCAL'].str.contains('caballeros')  pac['DLOCAL'].str.contains('e
jea')
pac[filtro].head()
In [10]: pac.loc[filtro,'DLOCAL'] = 'ejea de los caballeros' #Cambia en la columna DLOCAL t
odas las filas seleccionadas a ejea de los caballeros
Out[9]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CES
24320 2018 50 6 45
08/03/2018
16:52
08/03/2018
0:00
50 95
ejea de
los c
50600 1963 VI
25248 2018 50 7 186
21/03/2018
8:56
21/03/2018
0:00
50 95 ejea 50694 1954 CA
25637 2018 50 7 576
11/04/2018
10:09
11/04/2018
0:00
50 95 ejea 50600 1942 CA
25638 2018 50 7 577
11/04/2018
10:11
11/04/2018
0:00
50 95 ejea 50600 1969 CA
25762 2018 50 7 702
25/04/2018
8:50
25/04/2018
0:00
50 95 ejea 50600 1966 VI
Ocurrencias de 'ejea de los caballeros' 614
Ocurrencias de la palabra 'caballeros' 602
EjercicioEjercicio
Crear un mapa con los Municipios de aragón de alto contraste.Crear un mapa con los Municipios de aragón de alto contraste.
Indicad si es posible la comarca pero que quede bonito.Indicad si es posible la comarca pero que quede bonito.
In [14]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
GeoJSON y FoliumGeoJSON y Folium
Es muy fácil usar GeoJSON pero el resultado es muy pesado para verlo en jupyter.
Pero se puede salvar: codigos_postales_zaragoza_Hora8.html
(datos/codigos_postales_zaragoza_Hora8.html)
In [15]: codigos_postales_geo = 'datos/ZARAGOZA.geojson'
zaragoza = folium.Map(location=[41.6563,-0.8811], zoom_start=9)
def estilo(feature):
return {
'fillColor': '#ffff00',
'color': 'black',
'weight': 2,
'dashArray': '5, 5'
}
folium.GeoJson(
codigos_postales_geo,
style_function=estilo
).add_to(zaragoza)
zaragoza.save('datos/codigos_postales_zaragoza_Hora8.html')
Coropletas con FoliumCoropletas con Folium
Folium permite crear coropletas de una forma muy !exible.
Primero debemos crear un diccionario que contenga una clave y el valor que queremos
representar.
In [16]: import pandas as pd
pac = pd.read_csv('datos/ayudasPAC2018_Hora5.csv', sep=';', quotechar='')
pac = pac[pac['solicitante código provincia'] == 50]
pac_cp = pac.groupby('solicitante código postal').count()
pcap_cp_dict = pac_cp['solicitud año'].to_dict()
pac_cp.head()
Out[16]:
solicitud
año
solicitud
código
provincia
solicitud
código
agencia
solicitud
número
relativo
solicitud
registro
solicitud
fecha
solicitante
código
provincia
solicitante
código
municicipio
solicitante
localidad
solicitante
año
nacimiento
solicitante
estado
civil
so
solicitante
código
postal
5005 1 1 1 1 1 1 1 1 1 1 1 1
5083 1 1 1 1 1 1 1 1 1 1 1 1
20580 1 1 1 1 1 1 1 1 1 1 1 1
22806 2 2 2 2 2 2 2 2 2 2 2 2
22808 6 6 6 6 6 6 6 6 6 6 6 5
Después necesitamos una escala de colores.
In [17]: from branca.colormap import linear
colormap = linear.YlGn_09.scale(pac_cp['solicitud año'].min(), pac_cp['solicitud a
ño'].max())
colormap
Out[17]:
1 816
Ahora viene lo más complejo, asociar a cada valor de 'solicitante código postal' un color.
In [18]: color_dict = {key: colormap(pcap_cp_dict[key]) for key in pcap_cp_dict.keys()}
Y asegurarse que en función del COD_POSTAL de cada geometría se le de el color
adecuado.
In [19]: def computarColor(feature):
return {
'fillColor' : color_dict.get(int(feature[properties][COD_POSTAL]), '#f
fffff'),
'fillOpacity': 1
}
El siguiente paso ya lo hemos realizado antes.
Además añadimos un control para activar o desactivar la capa.
Todo se salva a solicitantes_pac_zaragoza_Hora8.html
(datos/solicitantes_pac_zaragoza_Hora8.html)
In [20]: codigos_postales_geo = 'datos/ZARAGOZA.geojson'
zaragoza = folium.Map(location=[41.6563,-0.8811], zoom_start=9)
folium.GeoJson(
codigos_postales_geo,
name = 'Demandantes PAC',
style_function = computarColor
).add_to(zaragoza)
folium.LayerControl().add_to(zaragoza)
zaragoza.save('datos/solicitantes_pac_zaragoza_Hora8.html')
EjercicioEjercicio
Estudiar la distribución en Aragón de la edad media de los solicitantes de laEstudiar la distribución en Aragón de la edad media de los solicitantes de la
PAC.PAC.
Disponemos de GeoJSON de Zaragoza, Huesca y TeruelDisponemos de GeoJSON de Zaragoza, Huesca y Teruel
Queremos saber si nos faltan datosQueremos saber si nos faltan datos
In [21]: #### Inicio del programa a desarrollar
#### Escribe tu código a continuación
#### Fin del programa a desarrollar
Pulsa aqui para ver la solución
Para !nalizarPara !nalizar
RecapitulaciónRecapitulación
1. Introducción al procesamiento de datos
2. Fuentes de datos
3. Introducción a Python/Jupyter
4. Carga de datos y exploración inicial
5. Limpieza y manipulación de datos
6. Análisis y visualización de datos
7. Modelos de datos
8. Visualización espacial de datos
Objetivos alcanzadosObjetivos alcanzados
¿Qué hemos hecho?
Hemos aprendido los fundamentos para trabajar con datos y portales de datos abiertos.
¿Qué hemos logrado?
Habéis obtenido competencias digitales básica para usar datos abiertos y herramientas
que mejoren la competitividad, procesos o información en el sector agroalimentario.

Más contenido relacionado

Similar a Trabajar en el sector agroalimentario aragonés con datos y portales de datos abiertos: jornada formativa

Fundamentos de Data Mining con R
Fundamentos de Data Mining con RFundamentos de Data Mining con R
Fundamentos de Data Mining con R
Software Guru
 
Práctica SQL en MYSQL
Práctica SQL en MYSQLPráctica SQL en MYSQL
Práctica SQL en MYSQL
lissette_torrealba
 
Curso SPSS básico.pdf
Curso SPSS básico.pdfCurso SPSS básico.pdf
la mejor forma de Conectar c# con mysql con archivos de configuracion
 la mejor forma de Conectar c# con mysql con archivos de configuracion  la mejor forma de Conectar c# con mysql con archivos de configuracion
la mejor forma de Conectar c# con mysql con archivos de configuracion
juandavid1118
 
Dashboard cde pentaho
Dashboard cde pentahoDashboard cde pentaho
Dashboard cde pentaho
Gregory Nick Toledo Veliz
 
Portabilidad y transportabilidad
Portabilidad y transportabilidadPortabilidad y transportabilidad
Portabilidad y transportabilidadjuanmanuelsalgado
 
Manual Tecnico
Manual TecnicoManual Tecnico
Manual Tecnico
makoto10
 
002_-_Metodologia_-_Area_de_rectangulo.pdf
002_-_Metodologia_-_Area_de_rectangulo.pdf002_-_Metodologia_-_Area_de_rectangulo.pdf
002_-_Metodologia_-_Area_de_rectangulo.pdf
RubEsmeraldaSolisBau
 
Matlab (1)
Matlab (1)Matlab (1)
Matlab (1)
numpad
 
Matlab
MatlabMatlab
Matlabford81
 
SolidQ Summit 2018 - Todo lo que un integrador de datos debería tener... y pa...
SolidQ Summit 2018 - Todo lo que un integrador de datos debería tener... y pa...SolidQ Summit 2018 - Todo lo que un integrador de datos debería tener... y pa...
SolidQ Summit 2018 - Todo lo que un integrador de datos debería tener... y pa...
SolidQ
 
Introduction to sas in spanish
Introduction to sas in spanishIntroduction to sas in spanish
Introduction to sas in spanish
Ajay Ohri
 
Actividad3 david a. condori tantani
Actividad3  david a. condori tantaniActividad3  david a. condori tantani
Actividad3 david a. condori tantani
Antonio Condori
 
Tallerprogramacion
TallerprogramacionTallerprogramacion
Tallerprogramacionjohanadoria
 
Semana 3 - Bases de Datos Avanzadas - Big Data - Sesion 3.pdf
Semana 3 - Bases de Datos Avanzadas - Big Data - Sesion 3.pdfSemana 3 - Bases de Datos Avanzadas - Big Data - Sesion 3.pdf
Semana 3 - Bases de Datos Avanzadas - Big Data - Sesion 3.pdf
romaldonolascorojas1
 

Similar a Trabajar en el sector agroalimentario aragonés con datos y portales de datos abiertos: jornada formativa (20)

Fundamentos de Data Mining con R
Fundamentos de Data Mining con RFundamentos de Data Mining con R
Fundamentos de Data Mining con R
 
Práctica SQL en MYSQL
Práctica SQL en MYSQLPráctica SQL en MYSQL
Práctica SQL en MYSQL
 
Curso SPSS básico.pdf
Curso SPSS básico.pdfCurso SPSS básico.pdf
Curso SPSS básico.pdf
 
la mejor forma de Conectar c# con mysql con archivos de configuracion
 la mejor forma de Conectar c# con mysql con archivos de configuracion  la mejor forma de Conectar c# con mysql con archivos de configuracion
la mejor forma de Conectar c# con mysql con archivos de configuracion
 
Dashboard cde pentaho
Dashboard cde pentahoDashboard cde pentaho
Dashboard cde pentaho
 
Introducción a Python
Introducción a PythonIntroducción a Python
Introducción a Python
 
Portabilidad y transportabilidad
Portabilidad y transportabilidadPortabilidad y transportabilidad
Portabilidad y transportabilidad
 
Introducción a DJango
Introducción a DJangoIntroducción a DJango
Introducción a DJango
 
Manual Tecnico
Manual TecnicoManual Tecnico
Manual Tecnico
 
002_-_Metodologia_-_Area_de_rectangulo.pdf
002_-_Metodologia_-_Area_de_rectangulo.pdf002_-_Metodologia_-_Area_de_rectangulo.pdf
002_-_Metodologia_-_Area_de_rectangulo.pdf
 
Matlab (1)
Matlab (1)Matlab (1)
Matlab (1)
 
Matlab
MatlabMatlab
Matlab
 
SolidQ Summit 2018 - Todo lo que un integrador de datos debería tener... y pa...
SolidQ Summit 2018 - Todo lo que un integrador de datos debería tener... y pa...SolidQ Summit 2018 - Todo lo que un integrador de datos debería tener... y pa...
SolidQ Summit 2018 - Todo lo que un integrador de datos debería tener... y pa...
 
Viernes Tecnicos DTrace
Viernes Tecnicos DTraceViernes Tecnicos DTrace
Viernes Tecnicos DTrace
 
Introduction to sas in spanish
Introduction to sas in spanishIntroduction to sas in spanish
Introduction to sas in spanish
 
Actividad3 david a. condori tantani
Actividad3  david a. condori tantaniActividad3  david a. condori tantani
Actividad3 david a. condori tantani
 
Tallerprogramacion
TallerprogramacionTallerprogramacion
Tallerprogramacion
 
Semana 3 - Bases de Datos Avanzadas - Big Data - Sesion 3.pdf
Semana 3 - Bases de Datos Avanzadas - Big Data - Sesion 3.pdfSemana 3 - Bases de Datos Avanzadas - Big Data - Sesion 3.pdf
Semana 3 - Bases de Datos Avanzadas - Big Data - Sesion 3.pdf
 
Temario
Temario Temario
Temario
 
andrea
andreaandrea
andrea
 

Último

"Guía de inversiones-Paraguay -(tesis)".
"Guía de inversiones-Paraguay -(tesis)"."Guía de inversiones-Paraguay -(tesis)".
"Guía de inversiones-Paraguay -(tesis)".
luzs79785
 
Características del ESTADO URUGUAYO establecidos en la Constitución
Características del ESTADO URUGUAYO establecidos en la ConstituciónCaracterísticas del ESTADO URUGUAYO establecidos en la Constitución
Características del ESTADO URUGUAYO establecidos en la Constitución
Graciela Susana Bengoa
 
Informe de Movilidad / Abril 2024 - Caja de Jubilaciones
Informe de Movilidad / Abril 2024 - Caja de JubilacionesInforme de Movilidad / Abril 2024 - Caja de Jubilaciones
Informe de Movilidad / Abril 2024 - Caja de Jubilaciones
Córdoba, Argentina
 
FICHA TÉCNICA POLVORINES SECTOR A Y B_ULTIMO-1.pdf
FICHA TÉCNICA POLVORINES SECTOR A Y B_ULTIMO-1.pdfFICHA TÉCNICA POLVORINES SECTOR A Y B_ULTIMO-1.pdf
FICHA TÉCNICA POLVORINES SECTOR A Y B_ULTIMO-1.pdf
MiguelCautiCordova
 
Microcredencial Universitaria en Innovación Local
Microcredencial Universitaria en Innovación LocalMicrocredencial Universitaria en Innovación Local
Microcredencial Universitaria en Innovación Local
Adrián Vicente Paños
 
obras por impuestos contrataciones con el estado
obras por impuestos contrataciones con el estadoobras por impuestos contrataciones con el estado
obras por impuestos contrataciones con el estado
abelardolima2020
 
Libro secundaria de lo humano y lo comunitario.pdf
Libro secundaria de lo humano y lo comunitario.pdfLibro secundaria de lo humano y lo comunitario.pdf
Libro secundaria de lo humano y lo comunitario.pdf
NADIAIVETTEDEMETRIOO
 
Folleto Cómo pedir la Credencial de Discapacidad versión Lectura Fácil.pdf
Folleto Cómo pedir la Credencial de Discapacidad versión Lectura Fácil.pdfFolleto Cómo pedir la Credencial de Discapacidad versión Lectura Fácil.pdf
Folleto Cómo pedir la Credencial de Discapacidad versión Lectura Fácil.pdf
claudiasilva082
 
SEPTIMA SESION DE CONSEJO TECNICO. MAYO 24..pptx
SEPTIMA SESION DE CONSEJO TECNICO. MAYO 24..pptxSEPTIMA SESION DE CONSEJO TECNICO. MAYO 24..pptx
SEPTIMA SESION DE CONSEJO TECNICO. MAYO 24..pptx
juanjimenez147030
 
#DigitalTierra nº 100 "Por Tierra y Aire en Irak"
#DigitalTierra nº 100 "Por Tierra y Aire en Irak"#DigitalTierra nº 100 "Por Tierra y Aire en Irak"
#DigitalTierra nº 100 "Por Tierra y Aire en Irak"
Ejército de Tierra
 
Febrero Doc - Metodologia y Gestion de proyectos
Febrero Doc - Metodologia y Gestion de proyectosFebrero Doc - Metodologia y Gestion de proyectos
Febrero Doc - Metodologia y Gestion de proyectos
infoenactuscolombia
 
Informe Estudio de Opinión en el municipio de Tonalá.pdf
Informe Estudio de Opinión en el municipio de Tonalá.pdfInforme Estudio de Opinión en el municipio de Tonalá.pdf
Informe Estudio de Opinión en el municipio de Tonalá.pdf
merca6
 
UNIDAD II MOVILIZAION EN LA DEFENSA INTEGRAL DE LA NACION
UNIDAD II MOVILIZAION EN LA DEFENSA INTEGRAL DE LA NACIONUNIDAD II MOVILIZAION EN LA DEFENSA INTEGRAL DE LA NACION
UNIDAD II MOVILIZAION EN LA DEFENSA INTEGRAL DE LA NACION
RusneiryChiquinquira
 
CCT 807-23 - Acuerdo Salarial Complementario 2024
CCT 807-23 - Acuerdo Salarial Complementario 2024CCT 807-23 - Acuerdo Salarial Complementario 2024
CCT 807-23 - Acuerdo Salarial Complementario 2024
Conam Mutualismo
 

Último (14)

"Guía de inversiones-Paraguay -(tesis)".
"Guía de inversiones-Paraguay -(tesis)"."Guía de inversiones-Paraguay -(tesis)".
"Guía de inversiones-Paraguay -(tesis)".
 
Características del ESTADO URUGUAYO establecidos en la Constitución
Características del ESTADO URUGUAYO establecidos en la ConstituciónCaracterísticas del ESTADO URUGUAYO establecidos en la Constitución
Características del ESTADO URUGUAYO establecidos en la Constitución
 
Informe de Movilidad / Abril 2024 - Caja de Jubilaciones
Informe de Movilidad / Abril 2024 - Caja de JubilacionesInforme de Movilidad / Abril 2024 - Caja de Jubilaciones
Informe de Movilidad / Abril 2024 - Caja de Jubilaciones
 
FICHA TÉCNICA POLVORINES SECTOR A Y B_ULTIMO-1.pdf
FICHA TÉCNICA POLVORINES SECTOR A Y B_ULTIMO-1.pdfFICHA TÉCNICA POLVORINES SECTOR A Y B_ULTIMO-1.pdf
FICHA TÉCNICA POLVORINES SECTOR A Y B_ULTIMO-1.pdf
 
Microcredencial Universitaria en Innovación Local
Microcredencial Universitaria en Innovación LocalMicrocredencial Universitaria en Innovación Local
Microcredencial Universitaria en Innovación Local
 
obras por impuestos contrataciones con el estado
obras por impuestos contrataciones con el estadoobras por impuestos contrataciones con el estado
obras por impuestos contrataciones con el estado
 
Libro secundaria de lo humano y lo comunitario.pdf
Libro secundaria de lo humano y lo comunitario.pdfLibro secundaria de lo humano y lo comunitario.pdf
Libro secundaria de lo humano y lo comunitario.pdf
 
Folleto Cómo pedir la Credencial de Discapacidad versión Lectura Fácil.pdf
Folleto Cómo pedir la Credencial de Discapacidad versión Lectura Fácil.pdfFolleto Cómo pedir la Credencial de Discapacidad versión Lectura Fácil.pdf
Folleto Cómo pedir la Credencial de Discapacidad versión Lectura Fácil.pdf
 
SEPTIMA SESION DE CONSEJO TECNICO. MAYO 24..pptx
SEPTIMA SESION DE CONSEJO TECNICO. MAYO 24..pptxSEPTIMA SESION DE CONSEJO TECNICO. MAYO 24..pptx
SEPTIMA SESION DE CONSEJO TECNICO. MAYO 24..pptx
 
#DigitalTierra nº 100 "Por Tierra y Aire en Irak"
#DigitalTierra nº 100 "Por Tierra y Aire en Irak"#DigitalTierra nº 100 "Por Tierra y Aire en Irak"
#DigitalTierra nº 100 "Por Tierra y Aire en Irak"
 
Febrero Doc - Metodologia y Gestion de proyectos
Febrero Doc - Metodologia y Gestion de proyectosFebrero Doc - Metodologia y Gestion de proyectos
Febrero Doc - Metodologia y Gestion de proyectos
 
Informe Estudio de Opinión en el municipio de Tonalá.pdf
Informe Estudio de Opinión en el municipio de Tonalá.pdfInforme Estudio de Opinión en el municipio de Tonalá.pdf
Informe Estudio de Opinión en el municipio de Tonalá.pdf
 
UNIDAD II MOVILIZAION EN LA DEFENSA INTEGRAL DE LA NACION
UNIDAD II MOVILIZAION EN LA DEFENSA INTEGRAL DE LA NACIONUNIDAD II MOVILIZAION EN LA DEFENSA INTEGRAL DE LA NACION
UNIDAD II MOVILIZAION EN LA DEFENSA INTEGRAL DE LA NACION
 
CCT 807-23 - Acuerdo Salarial Complementario 2024
CCT 807-23 - Acuerdo Salarial Complementario 2024CCT 807-23 - Acuerdo Salarial Complementario 2024
CCT 807-23 - Acuerdo Salarial Complementario 2024
 

Trabajar en el sector agroalimentario aragonés con datos y portales de datos abiertos: jornada formativa

  • 1. Introdución al procesamiento de datosIntrodución al procesamiento de datos Profesores: Javier Lacasta (jlacasta@unizar.es) F. Javier López (fjlopez@unizar.es) Javier Zarazaga (javy@unizar.es) Grupo de Sistemas de Información Avanzados ( )https://www.iaaa.es (https://www.iaaa.es)
  • 2. Introducción: Presentación de estas Jornadas. Tabla de contenidosTabla de contenidos Objetivos Contenidos y herramientas Primeros pasos para procesar datos
  • 3. ObjetivosObjetivos ¿Qué queremos hacer? Aprender a trabajar en el sector agroalimentario aragonés con datos y portales de datos abiertos. ¿Cómo lo queremos lograr? Capacitando en competencias digitales basadas en el uso de datos, datos abiertos y herramientas que mejoren la competitividad, procesos o información en el sector agroalimentario.
  • 4. ContenidosContenidos 1. Introducción al procesamiento de datos 2. Fuentes de datos 3. Introducción a Python/Jupyter 4. Carga de datos y exploración inicial 5. Limpieza y manipulación de datos 6. Análisis y visualización de datos 7. Modelos de datos 8. Visualización de datos espaciales
  • 5. Recordamos los requisitosRecordamos los requisitos Disponer de ordenador portátil con la distribución de Python 3.7 para ciencia de datos Anaconda Veri!car que efectivamente funciona escribiendo en un terminal: Esta presentación está disponible en: https://www.anaconda.com/distribution/ (https://www.anaconda.com/distribution/) jupyter notebook https://github.com/IAAA-Lab/curso-analisis-datos-python (https://github.com/IAAA- Lab/curso-analisis-datos-python)
  • 6. ¿Qué es Anaconda?¿Qué es Anaconda? Una distribución de código abierto de Python/R para ciencia de datos en Linux, Windows y macOS. Analizar datos con numpy y pandas. Visualizar con maplotlib. Gestor paquetes conda. +1500 paquetes de Python/R para datos.
  • 7. ¿Qué es Jupyter Notebook?¿Qué es Jupyter Notebook? Web: Un entorno web interactivo para crear Jupyter Notebooks . Documento: Un notebook es un documento que contiene una lista ordenada de celdas que pueden contener código, texto, diagramas. Ejecutable: La edición es interactiva y puede ejecutar código. Extensible: todas las sesiones las haremos sobre un notebook que al mismo tiempo puede verse como una presentación (extensión RISE ).
  • 8. Primeros pasos para procesar datosPrimeros pasos para procesar datos 1. Comprender el problema 2. Aproximarse de forma analítica al problema 3. Establecer los requisitos que deben tener los datos 4. Obtener los datos 5. Comenzar a explorarlos
  • 9. Comprensión del problemaComprensión del problema Es un paso obvio, pero con frecuencia olvidado. Tenemos que entender las características del problema.
  • 10. Aproximación analíticaAproximación analítica ¿Podemos expresar el problema como un problema que requiere de datos? ¿Podemos expresar el problema en términos de técnicas de procesamiento? ¿Conocemos las ventajas e inconvenientes de dichas técnicas? ¿Conocemos cómo implementar dichas técnicas (por ejemplo con Python)?
  • 11. RequisitosRequisitos ¿Nos vale cualquier tipo de dato? (Conocimiento del dominio) + (Técnicas) = Datos que necesitamos
  • 12. Captura de datosCaptura de datos Estructurados: un !chero CSV (hay !las y columnas) Semi estructurados: una pagina web (hay estructura y texto) No estructurados: un !chero PDF (no hay estructura o extracción muy difícil)
  • 13. ObjetivosObjetivos ¿Qué queremos hacer? Aprender a trabajar en el sector agroalimentario aragonés con datos y portales de datos abiertos. ¿Cómo lo queremos lograr? Capacitando en competencias digitales basadas en el uso de datos, datos abiertos y herramientas que mejoren la competitividad, procesos o información en el sector agroalimentario.
  • 14. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Datos de Open Data Aragón con las solicitudes de ayudas de la PAC 2018. In [2]: import pandas as pd pd.set_option('display.max_columns', None) pac = pd.read_csv( 'https://opendata.aragon.es/GA_OD_Core/download?view_id=78&filter_sql=CCOSEC%2 0%3D%272018%27&formato=csv&name=Pol%C3%ADtica%20Agraria%20Com%C3%BAn%20(PAC)%20201 8%20Arag%C3%B3n&nameRes=Solicitudes%20de%20ayudas%20PAC%202018&nameRes=Solicitudes %20de%20ayudas%20PAC%202018', sep=';', quotechar='"') pac.head() Out[2]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTADO SE 0 2018 22 1 1 2018- 05-15 13:48:30 2018- 05-29 00:00:00 22 130 BERNUES 22711 1995 SO V 1 2018 22 1 2 2018- 05-10 20:17:15 2018- 05-30 00:00:00 22 130 JACA 22700 1967 CA V 2 2018 22 1 3 2018- 03-01 09:38:32 2018- 03-01 00:00:00 22 130 JACA 22700 1955 SO V 3 2018 22 1 4 2018- 03-01 12:58:16 2018- 03-01 00:00:00 22 76 BINIÉS 22773 1947 CA V 4 2018 22 1 5 2018- 03-02 11:50:53 2018- 03-02 00:00:00 22 76 BINIÉS 22773 1947 SO V
  • 15. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Alternativamente, cargamos el !chero de un directorio de nuestro disco In [3]: import pandas as pd pd.set_option('display.max_columns', None) pac = pd.read_csv('datos/ayudasPAC2018.csv', sep=';', # Separados por punto y coma quotechar='"' # Delimitados por comillas dobles ) pac.head() Out[3]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTAD 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 16. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Obtenemos las dimensiones del conjunto de datos In [4]: print(pac.shape) Así que vemos que hay 44980 !las y 15 columnas. (44980, 14)
  • 17. Siguientes pasosSiguientes pasos Ahora habría que explorar los datos para: Comprender su contenido Evaluar su calidad Descubrir cualquier información preliminar relevante Determinar si hay que completar la información
  • 18. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Veamos que información disponemos: In [5]: # Muestra todos los valores únicos en la columna DLOCAL print("DLOCAL contiene", pac['DLOCAL'].unique().size, "valores distintos:") print(pac['DLOCAL'].unique()) # Muestra todos los valores únicos en la columna CESTADO print("CESTADO contiene", pac['CESTADO'].unique().size, "valores distintos:") print(pac['CESTADO'].unique()) ¿Qué problema tiene este conjunto de datos? Conclusión: Comprender el dato implica comprender los problemas que puede tener DLOCAL contiene 2935 valores distintos: ['BERNUES' 'JACA' 'BINIÉS' ... 'ANENTO' 'Villadoz' 'Villar de los Navarros'] CESTADO contiene 6 valores distintos: ['SO' 'CA' 'VI' 'None' 'DI' 'SJ']
  • 19. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Vamos a arreglar algunos de los problemas. Podemos normalizar valores Hay nombres de municipios en mayusculas y otros en minúsculas In [6]: pac['DLOCAL'] = pac['DLOCAL'].str.lower() print("DLOCAL contiene", pac['DLOCAL'].unique().size, "valores distintos:") El número de localidades se reduce de 2935 a 2360 si ignoramos las mayúsculas y las minúsculas. DLOCAL contiene 2360 valores distintos:
  • 20. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Podemos localizar casos raros Podemos ver lon nombres que sólo pasan una vez In [7]: unicos = pac['DLOCAL'].value_counts() == 1 valores = sorted(unicos[unicos].index.values) print(len(valores)) valores[:10] # Devuelve los 10 primeros Out[7]: 843 [' portellada, la ', '192', '22520', 'abadiño', 'abenfigo', 'abenfigo- castellote', 'ademuz', 'agramunt', 'aguatón', 'aguilar']
  • 21. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Podemos modi!car los datos de forma masiva Podemos eliminar los espacios que hay antes y después In [8]: pac['DLOCAL'] = pac['DLOCAL'].str.strip() unicos = pac['DLOCAL'].value_counts() == 1 valores = sorted(unicos[unicos].index.values) len(valores) Out[8]: 823
  • 22. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Podemos modi!car los datos de forma condicionada Podemos resolver un problema que hay con Ejea de los Caballeros In [9]: print("Ocurrencias de 'ejea de los caballeros'",len(pac[pac['DLOCAL'].str.contains ('ejea')])) print("Ocurrencias de la palabra 'caballeros'",len(pac[pac['DLOCAL'].str.contains( 'caballeros')])) filtro = ~pac['DLOCAL'].str.contains('caballeros') & pac['DLOCAL'].str.contains('e jea') pac[filtro].head() In [10]: pac.loc[filtro,'DLOCAL'] = 'ejea de los caballeros' #Cambia en la columna DLOCAL t odas las filas seleccionadas a ejea de los caballeros Out[9]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CES 24320 2018 50 6 45 08/03/2018 16:52 08/03/2018 0:00 50 95 ejea de los c 50600 1963 VI 25248 2018 50 7 186 21/03/2018 8:56 21/03/2018 0:00 50 95 ejea 50694 1954 CA 25637 2018 50 7 576 11/04/2018 10:09 11/04/2018 0:00 50 95 ejea 50600 1942 CA 25638 2018 50 7 577 11/04/2018 10:11 11/04/2018 0:00 50 95 ejea 50600 1969 CA 25762 2018 50 7 702 25/04/2018 8:50 25/04/2018 0:00 50 95 ejea 50600 1966 VI Ocurrencias de 'ejea de los caballeros' 614 Ocurrencias de la palabra 'caballeros' 602
  • 23. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Podemos analizar valores que deben depender de otros El código postal de Ejea de los Caballeros es 50600 . In [11]: pac[pac['CPOSDO'] == 50600]['DLOCAL'].unique() Out[11]: array(['ejea de los caballeros', 'san juan de mozarrifar', 'sta. anastasia', 'ejea delos caballeros', 'el sabinar', 'ejea de loscaballeros', 'zaragoza', 'bayo (el)', 'bardenas', 'valareña', 'tauste', 'pinsoro', 'farasdues', 'cariñena'], dtype=object)
  • 24. ContenidosContenidos 1. Introducción al procesamiento de datos 2. Fuentes de datos 3. Introducción a Python/Jupyter 4. Carga de datos y exploración inicial 5. Limpieza y manipulación de datos 6. Análisis y visualización de datos 7. Modelos de datos 8. Visualización de datos espaciales
  • 25. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Hemos resuelto problema, ¿pero hemos descubierto algo más? In [13]: pac[pac['CPOSDO'] == 50617]['DLOCAL'].unique() Como DLOCAL es texto libre hay posibilidades de error en CPOSDO Out[13]: array(['valareña', 'sabinar', 'santa anastasia', 'santa anastasi', 'el sabinar', 'sabinar (el)', 'ejea de los caballeros', 'sant anastasia', 'eje de los caballeros'], dtype=object)
  • 26. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Una vez corregidos los errores, podemos guardar los datos para su uso posterior In [14]: import csv pac.to_csv('datos/ayudasPAC2018_Hora1.csv', sep=";", quoting = csv.QUOTE_ALL, quot echar='"')
  • 27. Primeras conclusionesPrimeras conclusiones ¿Qué hemos obtenido hasta el momento? ¿Qué ventajas supone usar una herramienta como Jupyter/Python?
  • 29. Datos abiertosDatos abiertos Son considerados datos abiertos: Accesibles Reutilizables Sin exigencia de permisos especí!cos
  • 30. Fuentes principalesFuentes principales Fuentes cientí!cas Administraciones públicas Iniciativas de datos abiertos Comunidades de usuarios
  • 31. Fuentes de datos abiertas en EspañaFuentes de datos abiertas en España Multitud de portales creados por los diferentes niveles administrativos en España. También hay empresas que proporcionan de forma pública los datos que consideran relevantes. Ejemplos: Portal del gobierno de España: https://datos.gob.es/ Portal del gobierno de Aragón: https://opendata.aragon.es Catálogo de datos del Ayuntamiento Zaragoza: https://www.zaragoza.es/sede/portal/datos-abiertos/servicio/catalogo/ Portal de ESRI España: http://opendata.esri.es/ Catálogo de la IDEE: http://www.idee.es/csw-inspire- idee/srv/spa/catalog.search#/home
  • 32. Buscando informaciónBuscando información Catálogo de conjunto de datos navegable Un buscador con facetas para !ltrar la información Un API Web para automatizar las preguntas
  • 33. Recordamos los requisitosRecordamos los requisitos Disponer de ordenador portátil con la distribución de Python 3.7 para ciencia de datos Anaconda Veri!car que efectivamente funciona escribiendo en un terminal: Esta presentación está disponible en: https://www.anaconda.com/distribution/ (https://www.anaconda.com/distribution/) jupyter notebook https://github.com/IAAA-Lab/curso-analisis-datos-python (https://github.com/IAAA- Lab/curso-analisis-datos-python)
  • 34. Análisis de la informaciónAnálisis de la información Descripción del conjunto de datos (titulo, descripción, categoría) Formatos en los que está disponible: ¿Lo puedo procesar? Productor del dato: ¿Es !able? Extensión temporal: ¿Es del periodo de tiempo que necesito? Extensión espacial: ¿Cubre el área espacial que necesito? Periodicidad: Si lo necesito en el futuro ¿habrá datos? Licencia: ¿Puedo reutilizarlo (modalidad general básica, dominio público, otras licencias)?
  • 35. Obligaciones habituales derivadas de licencias abiertasObligaciones habituales derivadas de licencias abiertas Licencias abiertas: Reconocimiento (CC 4.0 BY, modalidad general básica) Compartir igual (CC 4.0 BY-SA, ODdL 1.0) Licencias no completamente abiertas: Sin obra derivada (CC 4.0 BY-ND) Uso no comercial (CC 4.0 BY-NC)
  • 36. Obtención del datoObtención del dato La descarga se puede hacer directamente, o delegar en la librería de procesamiento usada. Esto se verá en el siguiente tema. In [1]: import requests url = 'https://opendata.aragon.es/GA_OD_Core/download?' + 'view_id=78&filter_sql=CCOSEC%20%3D%272018%27&formato=csv&' + 'name=Pol%C3%ADtica%20Agraria%20Com%C3%BAn%20(PAC)%202018%20Arag%C3%B3n&' + 'nameRes=Solicitudes%20de%20ayudas%20PAC%202018&nameRes=Solicitudes%20de%20ayu das%20PAC%202018' myfile = requests.get(url) open('datos/ayudasPAC2018_Hora2.csv', 'wb').write(myfile.content) Out[1]: 5569621
  • 37. Otras fuentes de datosOtras fuentes de datos Hay muchas otras fuentes de datos abiertos fueras de los portales. Semi ocultas en páginas web Sin una descripción clara de lo que contienen En formatos no facilmente procesables La calidad depende de la institución creadora
  • 38. Colección de datos del INE.Colección de datos del INE. Di cil identi car la información que tienen y es necesario un proceso manual para descargarla. Al menos el formato suele ser CSV. https://www.ine.es/dyngs/INEbase/listaoperaciones.htm (https://www.ine.es/dyngs/INEbase/listaoperaciones.htm)
  • 39. Colección de datos del Ministerio de Agricultura.Colección de datos del Ministerio de Agricultura. Coleccion de PDFs accesibles a través de un buscador especi!co. Parte de la información exportable a excel pero los !cheros PDF contienen información tabular que se puede usar si no usan primero herramientas de extracción del contenido. https://www.mapa.gob.es/es/agricultura/temas/sanidad-vegetal/productos- !tosanitarios/registro/menu.asp (https://www.mapa.gob.es/es/agricultura/temas/sanidad- vegetal/productos-!tosanitarios/registro/menu.asp)
  • 40. Bases de datos de la Comisión EuropeaBases de datos de la Comisión Europea Colección de TSV sobre economía, transporte, medio ambiente, energia, y comercio entre otros a nivel europeo. https://ec.europa.eu/eurostat/data/database (https://ec.europa.eu/eurostat/data/database)
  • 41. Ejercicio de búsqueda de licenciasEjercicio de búsqueda de licencias Buscar las licencias habituales en las fuentes de datos mostradasBuscar las licencias habituales en las fuentes de datos mostradas
  • 42. Ejercicio de búsqueda de fuentes de datosEjercicio de búsqueda de fuentes de datos Buscar fuentes de datos sobre la PAC y su licenciaBuscar fuentes de datos sobre la PAC y su licencia
  • 43. Conceptos básicos de pythonConceptos básicos de python
  • 44. ¿Qué es Anaconda?¿Qué es Anaconda? Una distribución de código abierto de Python/R para ciencia de datos en Linux, Windows y macOS. Analizar datos con numpy y pandas. Visualizar con maplotlib. Gestor paquetes conda. +1500 paquetes de Python/R para datos.
  • 45. De nición de variables y asignaciónDe nición de variables y asignación Una variable es una posición de memoria del computador con un nombre al que se le puede asignar un valor Tipos de datos que vamos a usarTipos de datos que vamos a usar Enteros: ... -1, 0, 1, 2 ... Reales: -7.49, 12.9375 Booleanos: True, False Texto: "Cualquier texto entre comillas dobles", 'o comillas simples" De nición de una variable y asignación de un valorDe nición de una variable y asignación de un valor nombre = 3
  • 46. Ejemplo de de!nición y asignación de variablesEjemplo de de!nición y asignación de variables In [1]: entero = 3 real = 5.1 booleano = True texto = "Hola Mundo"
  • 47. Entrada / Salida y operaciones básicasEntrada / Salida y operaciones básicas Para poder usar las variables de!nidas necesitamos poder darles valores desde fuera del programa y poder mostrar el su valor por pantalla. Tambien tenemos que poder manipular su valor para calcular los resultados deseados.
  • 48. Operaciones de escritura por pantallaOperaciones de escritura por pantalla print ( variable a mostrar, segunda variable a mostrar, etc ) Operaciones básicas sobre variablesOperaciones básicas sobre variables variable = variable + 3 variable = variable2 * variable5 variable = variable2 - variable5 / variable9 (la división se ejecuta primero) Operaciones de lectura del tecladoOperaciones de lectura del teclado variable = input("Texto que se le quiere mostrar al usuario")
  • 49. Ejemplo de lectura, manipulación y escritura por pantallaEjemplo de lectura, manipulación y escritura por pantalla In [2]: tempTexto = input("Dígame una temperatura en celsius: ") # Lee un numero en format o texto tempReal = float(tempTexto) # Convierte un texto en r eal tempFar = tempReal * 9/5 + 32 # Convierte los grados print("La temperatura en Fahrenheit es", tempFar) # Muestra el resultado po r pantalla Dígame una temperatura en celsius: 15 La temperatura en Fahrenheit es 59.0
  • 50. Resumen de conversiones de tipos de datoResumen de conversiones de tipos de dato De real/texto a entero: int(variable) De entero/texo a real: !oat(variable) Cualquier cosa a texto: str(variable)
  • 51. Segundo ejemplo de lectura, manipulación y escritura por pantallaSegundo ejemplo de lectura, manipulación y escritura por pantalla In [3]: cantidad = int(input("Dígame una cantidad en pesetas: ")) print(cantidad, "pesetas son", round(cantidad / 166.386, 2), "euros") #round redon dea un real al numero de decimales indicado print(str(cantidad) + " pesetas son " + str(round(cantidad / 166.386, 2)) + " euro s") Dígame una cantidad en pesetas: 10 10 pesetas son 0.06 euros 10 pesetas son 0.06 euros
  • 52. Ejercicio de lectura, manipulación y escritura por pantallaEjercicio de lectura, manipulación y escritura por pantalla Haz un programa que convierta de metros a pies. 1 metro son 3,28084 pies.Haz un programa que convierta de metros a pies. 1 metro son 3,28084 pies. In [4]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 53. Pulsa aqui para ver la solución
  • 54. CondidionesCondidiones Permiten dividir el !ujo de ejecución entre multiples opiones. Ejemplo de uso: En una columna numérica sustituir el valor por Negativo si es menor que 0 , Zero si es igual a 0 y Positivo al resto. if condicion: ejecutame si condicion es True elif condicion_alternativa: ejecutame si condicion es False y condicion_alterantiva True elif otra_condicion_mas: ejecutame si condicion y condicion_alternativa son False y otra_condicion_mas es True else: si todas las condiciones son False
  • 55. ¿Qué es Jupyter Notebook?¿Qué es Jupyter Notebook? Web: Un entorno web interactivo para crear Jupyter Notebooks . Documento: Un notebook es un documento que contiene una lista ordenada de celdas que pueden contener código, texto, diagramas. Ejecutable: La edición es interactiva y puede ejecutar código. Extensible: todas las sesiones las haremos sobre un notebook que al mismo tiempo puede verse como una presentación (extensión RISE ).
  • 56. Ejemplos de condicionesEjemplos de condiciones In [5]: dia = int(input("Introduzca un dia de Enero: ")) if(dia > 31): print("Dia no valido") else: print("Dia valido") In [6]: dia = int(input("Introduzca un dia de Enero: ")) if(dia <=0 or dia > 31): print("Dia no valido") else: print("Dia valido") In [7]: dia = int(input("Introduzca un dia de Enero: ")) if(dia >=1 and dia <=31): print("Dia valido") else: print("Dia no valido") Introduzca un dia de Enero: 1 Dia valido Introduzca un dia de Enero: 2 Dia valido Introduzca un dia de Enero: 3 Dia valido
  • 57. Ejercicio de condicionesEjercicio de condiciones Haz un programa que lea un día de enero y diga si está en la primera quincena, en la segunda o si noHaz un programa que lea un día de enero y diga si está en la primera quincena, en la segunda o si no es valido.es valido. In [8]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 58. Pulsa aqui para ver la solución
  • 59. IteracionesIteraciones Permiten ejecutar la misma instrucción multiples veces, cada vez con valores diferentes de sus variables Por ejemplo: Recorrer todas las !las de una tabla de datos para calcular la media de los valores de cada !la for valor in rango de cualquier tipo: ejecuto un conjunto de operaciones valor contiene un valor en el rango while condición igual a True: ejecuto un conjunto de operaciones que modifican las variables de la condición esperando que deje en algún momento de ser True
  • 60. Ejemplos de iteracionesEjemplos de iteraciones In [9]: inicio=1; fin=10 for i in range (inicio, fin): print(i, end = " " ) #El segundo parametro del print hace que no se cambie de linea al mostrar por pantalla In [10]: inicio=1; fin=10 while inicio < fin : print(inicio, end = " " ) inicio = inicio +1 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
  • 61. Ejercicio de iteracionesEjercicio de iteraciones Haz un programa que muestre los pares mayores de 0 y menores que 20.Haz un programa que muestre los pares mayores de 0 y menores que 20. Nota: El operador % calula el resto de la división entera. x % 2 será cero si el numero x es par.Nota: El operador % calula el resto de la división entera. x % 2 será cero si el numero x es par. In [11]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 62. Pulsa aqui para ver la solución
  • 63. FuncionesFunciones Podemos reutilizar código mediante la de!nición de funciones con def : In [12]: def fib(n): a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a+b print() Calculamos el valor de fib(100) y fib(1000) In [13]: fib(100) fib(1000) 0 1 1 2 3 5 8 13 21 34 55 89 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
  • 64. ListasListas Estructura lineal que almacena multiples valores y se accede a través de un índice In [14]: vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] print (vector) for i in range(len(vector)): print (i, vector[i]) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10
  • 65. MódulosMódulos Una clase es una agrupación de funcionalidad para manipular datos de un tipo concreto. Ejemplos de módulos: Representación de una tabla para manipular su contenido Representación de un !chero para leerlo / escribirlo Representación de una !gura para de!nir su contenido y mostrarla por pantalla Los módulos tiene que importarse para poder ser usados In [15]: import random random.randint(0,5) Out[15]: 4
  • 66. Primeros pasos para procesar datosPrimeros pasos para procesar datos 1. Comprender el problema 2. Aproximarse de forma analítica al problema 3. Establecer los requisitos que deben tener los datos 4. Obtener los datos 5. Comenzar a explorarlos
  • 67. Ejemplo de uso de métodos en pandasEjemplo de uso de métodos en pandas Los formatos soportados y como leerlos está descrito en: Formato Lectura Escritura csv pd.read_csv() pac.to_csv() json pd.read_json() pac.to_json() excel pd.read_excel() pac.to_excel() hdf pd.read_hdf() pac.to_hdf() sql pd.read_sql() pac.to_sql() ... ... ... Cada operación requirere un conjunto de parametros indicado en la documentacion. Por ejemplo: Para leer un !chero hay que pasarle como mínimo su ruta de acceso(sea URL o nombre !chero) Para escribir un !chero hay que proporcionarle como mínimodonde guardarlo https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html (https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html)
  • 68. EjemploEjemplo In [17]: #cargamos un fichero csv indicandole el separador pac = pd.read_csv('datos/ayudasPAC2018.csv', sep=';', quotechar='"') #guardamos la tabla en un fichero pac.to_csv('datos/ayudasPAC2018_Hora3.csv') #mostramos las primeras filas por pantalla pac.head() Out[17]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTAD 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 69. Series y DataFramesSeries y DataFrames Conceptos claves en pandas. Serie: lista etiquetada (índices) con valores del mismo tipo Data Frame: tabla etiquetada (nombres de columnas) compuesta de series In [18]: for columna in pac.columns: serie = pac[columna] print("La columna {0} es una Serie de tamaño {1} con {2} valor(es) distinto (s)" .format(serie.name, len(serie.index), len(serie.unique()))) La columna CCOSEC es una Serie de tamaño 44980 con 1 valor(es) distinto(s) La columna CPROVI es una Serie de tamaño 44980 con 3 valor(es) distinto(s) La columna CAGENC es una Serie de tamaño 44980 con 48 valor(es) distinto(s) La columna CCORRE es una Serie de tamaño 44980 con 2335 valor(es) distinto(s) La columna FREGIS es una Serie de tamaño 44980 con 23987 valor(es) distinto(s) La columna FSOLIC es una Serie de tamaño 44980 con 108 valor(es) distinto(s) La columna CPRODO es una Serie de tamaño 44980 con 38 valor(es) distinto(s) La columna CMUNDO es una Serie de tamaño 44980 con 314 valor(es) distinto(s) La columna DLOCAL es una Serie de tamaño 44980 con 2935 valor(es) distinto(s) La columna CPOSDO es una Serie de tamaño 44980 con 1427 valor(es) distinto(s) La columna CANONAC es una Serie de tamaño 44980 con 100 valor(es) distinto(s) La columna CESTADO es una Serie de tamaño 44980 con 6 valor(es) distinto(s) La columna SEXO es una Serie de tamaño 44980 con 3 valor(es) distinto(s) La columna RNUM es una Serie de tamaño 44980 con 44980 valor(es) distinto(s)
  • 70. Importación y Exploración de datosImportación y Exploración de datos
  • 71. Importación y Exploración de datosImportación y Exploración de datos En esta hora se va a describir la forma de cargar / guardar datos tabulares en Python desde diferentes formatos (.csv, .json, .xlsx etc.) y diferentes formas de visualizar su contenido para hacernos una idea de los problemas que tienen dichos datos. En la siguiente hora se mostrará como corregir diferentes tipos de problemas. Tabla de contenidosTabla de contenidos Descripción de los datos a manipular Procesamiento de !cheros CSV (Lectura / Exploración / Escritura) Procesamiento de !cheros en otros formatos
  • 72. Descripción de los datos a manipularDescripción de los datos a manipular Vamos a practicar la carga de un conjuntos datos en un Jupyter Notebook con la librería Pandas de un !chero !chero CSV sobre la PAC que descargaruemos desde Open Data Aragón. Documentación: Datos: Fichero local: datos/ayudasPAC2018.csv https://opendata.aragon.es/datos/catalogo/dataset/politica-agraria- comun-pac-2018-aragon (https://opendata.aragon.es/datos/catalogo/dataset/politica- agraria-comun-pac-2018-aragon) https://opendata.aragon.es/GA_OD_Core/download? view_id=78&!lter_sql=CCOSEC%20%3D%272018%27&formato=csv&name=Pol%C3%ADt (https://opendata.aragon.es/GA_OD_Core/download? view_id=78&!lter_sql=CCOSEC%20%3D%272018%27&formato=csv&name=Pol%C3%ADt
  • 73. Lectura y escritura de !cheros con pandasLectura y escritura de !cheros con pandas Los formatos soportados y como leerlos está descrito en: Formato Lectura Escritura csv pd.read_csv() pac.to_csv() json pd.read_json() pac.to_json() excel pd.read_excel() pac.to_excel() hdf pd.read_hdf() pac.to_hdf() sql pd.read_sql() pac.to_sql() ... ... ... Cada operación de lectura escritura de un formato diferente tiene parametros diferentes para ajustar la con!guración. https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html (https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html)
  • 74. Leer CSVLeer CSV Usamos pandas.read_csv() para leer el !chero cvs y guardarlos en un dataframe Necesitamos como parámetros: La localización del !chero Indicar que los valores estan separados por ; . Se usa el parametro sep = ';' Indicar que los valores están entre " . Se usa el parametro quotechar = '"' Hay muchos más parametros a tener en cuenta: La carga puede hacerse desde !cheros en la web y locales. https://pandas.pydata.org/pandas- docs/stable/reference/api/pandas.read_csv.html (https://pandas.pydata.org/pandas- docs/stable/reference/api/pandas.read_csv.html)
  • 75. Comprensión del problemaComprensión del problema Es un paso obvio, pero con frecuencia olvidado. Tenemos que entender las características del problema.
  • 76. Carga de !cheros localesCarga de !cheros locales In [2]: import pandas as pd localizacion = 'datos/ayudasPAC2018.csv' pac = pd.read_csv(localizacion, sep=';', quotechar='"') print("Hecho") Hecho
  • 77. Explorar el contenidoExplorar el contenido Independientemente del formato una vez cargado el !chero tabular, una vez cargados con Pandas todos los !cheros se procesan igual Visualizar la estructura de la tabla Alteración de cabeceras Ajuste de columnas Generación de resumenes
  • 78. Exploración básica con PandasExploración básica con Pandas Visualizar la estructura de la tabla Visualizar los tipos de datos de las columnas y numero de elementos Estadisticas del contenido de las columnas
  • 79. Visualización de la estructura de la tablaVisualización de la estructura de la tabla dataframe.head(n) para ver las primeras n !las del dataframe. dataframe.tail(n) para ver las últimas n !las del dataframe. In [3]: pac.head(5) Out[3]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTAD 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 80. Ejercicio de visualizaciónEjercicio de visualización Muestra las últimas 3 !las del dataframe pac.Muestra las últimas 3 !las del dataframe pac. In [4]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 81. Pulsa aqui para ver la solución
  • 82. Visualización de tipos de datoVisualización de tipos de dato Nos devuelve una descripción de los tipos de datos de cada columna, si hay valores y total de !las ocupadas dataframe.info() In [5]: pac.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 44980 entries, 0 to 44979 Data columns (total 14 columns): CCOSEC 44980 non-null int64 CPROVI 44980 non-null int64 CAGENC 44980 non-null int64 CCORRE 44980 non-null int64 FREGIS 44980 non-null object FSOLIC 44980 non-null object CPRODO 44980 non-null int64 CMUNDO 44980 non-null int64 DLOCAL 44980 non-null object CPOSDO 44980 non-null int64 CANONAC 44980 non-null object CESTADO 44980 non-null object SEXO 44980 non-null object RNUM 44980 non-null int64 dtypes: int64(8), object(6) memory usage: 4.8+ MB
  • 83. Estadisticas de las columnasEstadisticas de las columnas Devuelve un resumen estadistico de las columnas. Si el parametro all, solo muestra las columnas numericas. Algunos valores tendrán el valor NaN porque no tienen sentido para el tipo de datosde dicha columna. Para datos númericos incluye el numero de elementos (count), media (mean), desviación estandard (str), valor minimo y maximo (min, max) y los percentiles 25, 50 y 75 Para el resto de datos (texto y fechas), además del numero de elementos (count), el valor mas común (top) y su frecuencia (freq). Unique indica el numero de valores distintos dataframe.describe(include = "all")
  • 84. Aproximación analíticaAproximación analítica ¿Podemos expresar el problema como un problema que requiere de datos? ¿Podemos expresar el problema en términos de técnicas de procesamiento? ¿Conocemos las ventajas e inconvenientes de dichas técnicas? ¿Conocemos cómo implementar dichas técnicas (por ejemplo con Python)?
  • 85. Modi car cabecerasModi car cabeceras Tener cabeceras no legibles di!culta la interpretación de los datos dataframe.columns contiene las cabeceras de nuestros datos. In [7]: print(pac.columns) Index(['CCOSEC', 'CPROVI', 'CAGENC', 'CCORRE', 'FREGIS', 'FSOLIC', 'CPRODO', 'CMUNDO', 'DLOCAL', 'CPOSDO', 'CANONAC', 'CESTADO', 'SEXO', 'RNUM'], dtype='object')
  • 86. Como los nombres son poco útiles, vamos a crear una lista de cabeceras alternativa y cambiar las que tenemos In [8]: headers = ['solicitud año','solicitud código provincia','solicitud código agencia' ,'solicitud número relativo', 'solicitud registro', 'solicitud fecha','solicitante código provincia', 'solicitante código municicipio', 'solicitante localidad', 'solicitante código postal','solicitante año n acimiento','solicitante estado civil','solicitante sexo', 'número fila'] pac.columns = headers pac.head(5) Out[8]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solic e 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 87. Ahora podemos interpretar mejor el resumen de los datos In [9]: pac.describe(include = "all") Out[9]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad count 44980.0 44980.000000 44980.000000 44980.000000 44980 44980 44980.000000 44980.000000 44980 unique NaN NaN NaN NaN 23987 108 NaN NaN 2935 top NaN NaN NaN NaN 14/05/2018 14:27 31/05/2018 0:00 NaN NaN ZARAGOZA freq NaN NaN NaN NaN 11 1864 NaN NaN 2866 mean 2018.0 39.573366 23.413762 616.141574 NaN NaN 39.668831 153.193597 NaN std 0.0 12.454863 12.361772 472.297968 NaN NaN 12.629092 132.318678 NaN min 2018.0 22.000000 1.000000 1.000000 NaN NaN 1.000000 1.000000 NaN 25% 2018.0 22.000000 13.000000 237.000000 NaN NaN 22.000000 61.000000 NaN 50% 2018.0 44.000000 23.000000 511.000000 NaN NaN 44.000000 128.000000 NaN 75% 2018.0 50.000000 32.000000 895.000000 NaN NaN 50.000000 222.000000 NaN max 2018.0 50.000000 48.000000 4004.000000 NaN NaN 50.000000 912.000000 NaN
  • 88. Ejercicio de analisis del contenidoEjercicio de analisis del contenido Dada la tabla de resumen de los datos identi!ca posibles problemas en losDada la tabla de resumen de los datos identi!ca posibles problemas en los datos.datos.
  • 89. Pulsa aqui para ver la solución
  • 90. Analisis detallado del contenidoAnalisis detallado del contenido El analisis general te puede dar una idea de que hay algo mal, pero hace falta un analis más detallado de las columnas para identi!car problemas Una buena politica de analisis es visualizar los valores distintos. El método únique del dataframe nos permite analizar cada columna. In [10]: print("Estados civiles", pac['solicitante estado civil'].unique()) print("Localidades", pac['solicitante localidad'].unique()) Hay muchas localidades y por defecto no se muestran todas. Si queremos mostrarlas hay que con!gurar el entorno. Estados civiles ['SO' 'CA' 'VI' 'None' 'DI' 'SJ'] Localidades ['BERNUES' 'JACA' 'BINIÉS' ... 'ANENTO' 'Villadoz' 'Villar de los Navarros']
  • 91. Mostrar frecuencias de valoresMostrar frecuencias de valores Cuando hay muchos valores y no se muestran todos, es interesante mostrarlos junto con el numero de ocurrencias de cada valor. Aquellos valores con pocas ocurrencias, es posible que sean errores. In [11]: serie = pac['solicitante código postal'].value_counts() serie Out[11]: 50660 816 50600 616 22500 565 22300 533 22520 495 ... 25450 1 46000 1 50110 1 3015 1 31840 1 Name: solicitante código postal, Length: 1427, dtype: int64
  • 92. ¿Comó sabemos cuales son las dimensiones del problema? Contamos las veces que ocurre cada valor y mostramos un histograma ¿Cómo se distribuyen las peticiones entre localidades de menos de 100 peticiones? In [12]: import matplotlib.pyplot as plt plt.hist(serie, bins = 5, log = True) Out[12]: (array([1.365e+03, 5.000e+01, 7.000e+00, 4.000e+00, 1.000e+00]), array([ 1., 164., 327., 490., 653., 816.]), <a list of 5 Patch objects>)
  • 93. RequisitosRequisitos ¿Nos vale cualquier tipo de dato? (Conocimiento del dominio) + (Técnicas) = Datos que necesitamos
  • 94. De nición de subconjuntosDe nición de subconjuntos Además de analizar los datos, puede ser necesario !ltrarlos para quedarnos con un subconjunto de las !las y columnas originales Tareas a realizar: Filtrado de columnas Filtrado de !las
  • 95. Eliminar columnasEliminar columnas Podemos eliminar las columnas dado su nombre. Ej: numero !la. Operación drop: borra las columnas indicadas en el vector [] In [14]: pac2 = pac.drop(['número fila'], axis='columns') pac2.head(3) Observad que hemos tenido que actualizar el valor de pac . Out[14]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solic e 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO
  • 96. Ejercicio de borrado de columnasEjercicio de borrado de columnas Borra las !las solicitud registro y solicitud fecha y muestra los primeros 5Borra las !las solicitud registro y solicitud fecha y muestra los primeros 5 resultadosresultados In [15]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 97. Pulsa aqui para ver la solución
  • 98. Selección y eliminación de !lasSelección y eliminación de !las Tambien es posible seleccionar todas las !las que cumplen una condicion o eliminarlas Se seleccionan los indices a coger y se extraen o borran In [16]: is_jaca = pac2['solicitante localidad']=='JACA' print (is_jaca) 0 False 1 True 2 True 3 False 4 False ... 44975 False 44976 False 44977 False 44978 False 44979 False Name: solicitante localidad, Length: 44980, dtype: bool
  • 99. In [17]: pac_jaca = pac2[is_jaca] pac_nojaca = pac2.drop(pac2.index[is_jaca]) print("Original:", pac2.shape) print("Jacas:", pac_jaca.shape) print("No Jacas:", pac_nojaca.shape) pac_jaca.head(5) Out[17]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento sol 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 7 2018 22 1 8 07/03/2018 10:30 07/03/2018 0:00 22 130 JACA 22700 1960 SO 27 2018 22 1 28 15/03/2018 16:11 15/03/2018 0:00 22 130 JACA 22714 1966 SO 29 2018 22 1 30 15/03/2018 17:19 15/03/2018 0:00 22 130 JACA 22700 1969 SO Original: (44980, 13) Jacas: (85, 13) No Jacas: (44895, 13)
  • 100. Ejercicio de !ltrado de !lasEjercicio de !ltrado de !las Crea una tabla con las personas en el CP: 28006 sin año de nacimiento en laCrea una tabla con las personas en el CP: 28006 sin año de nacimiento en la PAC (Valor None)PAC (Valor None) In [18]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 101. Pulsa aqui para ver la solución Guardar CSVGuardar CSV Pandas nos permite guardar los datos en formato CSV con dataframe.to_csv() . Por ejemplo: Pero hay más formatos y opciones: pac.to_csv("pac-2018.csv") import csv pac.to_csv('datos/ayudasPAC2018_Hora4.csv', sep=";", quoting = csv.QUOTE_ALL, quo techar='"')
  • 102. Captura de datosCaptura de datos Estructurados: un !chero CSV (hay !las y columnas) Semi estructurados: una pagina web (hay estructura y texto) No estructurados: un !chero PDF (no hay estructura o extracción muy difícil)
  • 103. In [19]: pac.to_json('datos/pac-2018-rec_Hora4.json', orient='records') pacjson = pd.read_json('datos/pac-2018-rec_Hora4.json', orient='records') pacjson.head(5) Out[19]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solic e 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 104. In [20]: pac.to_html('datos/pac-2018_Hora4.html') pachtml = pd.read_html('datos/pac-2018_Hora4.html', index_col = 0) pachtml[0].head(5) Out[20]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solic 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 105. In [21]: pac.to_excel('datos/pac-2018_Hora4.xlsx', sheet_name = "PAC2018") pacexcel = pd.read_excel('datos/pac-2018_Hora4.xlsx', sheet_name = "PAC2018", inde x_col = 0) pacexcel.head(5) Out[21]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solic e 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 107. Limpieza de datos: Procesar una colección de datos para detectar y corregir problemas de todo tipo: valores erroneos o inexistentes, inconsistencias y formatos heterogéneos. Tabla de contenidosTabla de contenidos Identi!car y tratar los datos que faltan. Estandarización. Normalización. Clasi!cación.
  • 108. Identi car y tratar los valores que faltanIdenti car y tratar los valores que faltan Primero preparamos los datos que preparamos en la hora anterior. In [1]: import pandas as pd pac = pd.read_csv('datos/ayudasPAC2018.csv', sep=';', quotechar='"') headers = ['solicitud año','solicitud código provincia','solicitud código agencia' ,'solicitud número relativo', 'solicitud registro', 'solicitud fecha','solicitante código provincia', 'solicitante código municicipio', 'solicitante localidad', 'solicitante código postal','solicitante año n acimiento','solicitante estado civil','solicitante sexo', 'número fila'] pac.columns = headers pac.head(5) Out[1]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solic e 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 109. Armonizar etiquetas de los valores que faltanArmonizar etiquetas de los valores que faltan Cuando una posición de la tabla no tiene valor, Pandas le asigna el valor " NaN " ( Not a Number ). En nuestros datos sin embargo se usa el texto None . Usamos replace para reemplazar todos los None por NaN para poder contarlos. El parametro implace hace que en vez de generarse un nuevo DataFrame (tabla) la modi!cación se haga dentro del mismo DataFrame . In [2]: import numpy as np pac.replace("None", np.nan, inplace = True)
  • 110. Análisis de columnas en las que faltan valoresAnálisis de columnas en las que faltan valores Una vez armonizados los valores que faltan, tenemos que analizar donde están para poder tratarlos. Generamos una copia del DataFrame ( datosQueFaltan ) que contenga sólo las posiciones sin datos y las contamos. En los resultados se puede ver que hay unos pocos problemas en fechas de solicitud y localidad pero muchos en año nacimiento, estado civil y sexo.
  • 111. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Comprobemos primero la versión de Python instalada. Pulsemos mayúsculas+retorno para ejecutar el código de la celda. In [1]: !python -V Python 3.7.4
  • 112. Gestionar los datos que faltanGestionar los datos que faltan Existen dos alternativas principales, eliminación del dato o estimación de su valor: Eliminar toda la !la o columna. Reemplazar por la media o la más frecuente de la columna. Reemplazar usando otra función matemática. Posible corrección de los datos de la PAC: Fecha, Estado civil, Sexo: reemplazar por el más frecuente. Localidad: eliminar !las con `NaN`. Año de nacimiento: reemplazar por la media (redondeada).
  • 113. Reemplazamos el Estado civil por el más frecuente. In [4]: valorComun = pac['solicitante estado civil'].value_counts().idxmax() pac["solicitante estado civil"].replace(np.nan, valorComun, inplace = True)
  • 114. Eliminamos las !las con NaN en la columna Fecha. In [5]: aBorrar = pac['solicitud fecha'].isnull() pac.drop(pac.index[aBorrar], inplace = True)
  • 115. Cambiamos la Fecha de nacimiento vacía por su media. In [6]: media = pac["solicitante año nacimiento"].astype("float").mean(axis = 0) pac["solicitante año nacimiento"].replace(np.nan, media, inplace = True) pac["solicitante año nacimiento"] = pac["solicitante año nacimiento"].astype("int6 4")
  • 116. Ejercicio de limpieza de casillas vacíasEjercicio de limpieza de casillas vacías Termina de limpiar los datos vacíos de las columnas que faltan y muestra queTermina de limpiar los datos vacíos de las columnas que faltan y muestra que ya no quedan columnas por limpiarya no quedan columnas por limpiar In [7]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 117. Pulsa aqui para ver la solución
  • 118. 2. Estandarización2. Estandarización El el proceso por el que se transforma los datos en un formato común que permite realizar una comparación con sentido. Pasar todos los nombres de municipios a minúsculas. Quitar horas de las fechas. Corregir nombres con errores. Corregir correlaciones erroneas entre atributos. ...
  • 119. Veamos la situación de partida. In [8]: pac['solicitante localidad'].value_counts() Out[8]: ZARAGOZA 2864 TAUSTE 749 HUESCA 727 EJEA DE LOS CABALLEROS 521 Zaragoza 519 ... MONREAL DEL CAMNPO 1 SANTA ENGRACIA -TAUSTE 1 MUNÉBREGA 1 Valmadrid 1 SAN MARTIN DE LA VIRGEN DE MONCAYO 1 Name: solicitante localidad, Length: 2924, dtype: int64
  • 120. Pasamos todos nombres de municipios a minúsculas. In [9]: pac['solicitante localidad']=pac['solicitante localidad'].str.lower() pac['solicitante localidad'].value_counts() Out[9]: zaragoza 3394 huesca 860 tauste 813 ejea de los caballeros 598 barbastro 525 ... terue 1 mora la nova 1 torre del comte 1 valderrrobres 1 aguilar 1 Name: solicitante localidad, Length: 2352, dtype: int64
  • 121. Quitar horas de las fechasQuitar horas de las fechas Convertimos las fechas en tipo datetime (día y hora) en date (día). Podríamos hacer otras operaciones con fechas si fuera necesario, tales como seleccionar rangos de fechas. In [10]: pac['solicitud registro']= pd.to_datetime(pac['solicitud registro']) print(pac['solicitud registro'][0]) pac['solicitud registro']= pac['solicitud registro'].dt.date print(pac['solicitud registro'][0]) 2018-05-15 13:48:00 2018-05-15
  • 122. Corregir errores en los nombresCorregir errores en los nombres Es recomendable revisar aquellas componentes que tienen pocas ocurrencias para ver si están bien escritas. El entorno de jupyter no es necesariamente el más adecuado para esta tarea. Lo más recomendable es guardar el conteo de ocurrencias en un !chero y revisarlo manualmente. Los nombres se pueden corregir en la fuente original o si fuera un proceso repetible programar los cambios en python .
  • 123. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Datos de Open Data Aragón con las solicitudes de ayudas de la PAC 2018. In [2]: import pandas as pd pd.set_option('display.max_columns', None) pac = pd.read_csv( 'https://opendata.aragon.es/GA_OD_Core/download?view_id=78&filter_sql=CCOSEC%2 0%3D%272018%27&formato=csv&name=Pol%C3%ADtica%20Agraria%20Com%C3%BAn%20(PAC)%20201 8%20Arag%C3%B3n&nameRes=Solicitudes%20de%20ayudas%20PAC%202018&nameRes=Solicitudes %20de%20ayudas%20PAC%202018', sep=';', quotechar='"') pac.head() Out[2]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTADO SE 0 2018 22 1 1 2018- 05-15 13:48:30 2018- 05-29 00:00:00 22 130 BERNUES 22711 1995 SO V 1 2018 22 1 2 2018- 05-10 20:17:15 2018- 05-30 00:00:00 22 130 JACA 22700 1967 CA V 2 2018 22 1 3 2018- 03-01 09:38:32 2018- 03-01 00:00:00 22 130 JACA 22700 1955 SO V 3 2018 22 1 4 2018- 03-01 12:58:16 2018- 03-01 00:00:00 22 76 BINIÉS 22773 1947 CA V 4 2018 22 1 5 2018- 03-02 11:50:53 2018- 03-02 00:00:00 22 76 BINIÉS 22773 1947 SO V
  • 124. Una vez localizado un nombre con error miramos sus variantes para poder corregirlas. Solo tiene sentido hacerlo por programa si se va a tener que replicar la limpieza en el futuro de otra fuente similar con el mismo tipo de problemas, ya que aunque es costoso crear el programa ahorra mucho tiempo si lo tienes que hacerlo a mano muchas veces In [12]: cp50600 = pac['solicitante código postal'] == 50600 contieneEjea = pac['solicitante localidad'].str.contains('ejea') print(pac[cp50600]['solicitante localidad'].unique()) In [13]: pac.loc[cp50600 & contieneEjea, 'solicitante localidad'] = 'ejea de los caballero s' print(pac[cp50600]['solicitante localidad'].unique()) ['ejea de los caballeros' 'san juan de mozarrifar' 'ejea de los c' 'sta. anastasia' 'ejea delos caballeros' 'el sabinar' 'ejea de loscaballeros' 'ejea' 'zaragoza' 'ejea de los cabaleros' 'bayo (el)' 'bardenas' 'valareña' 'ejea de los cabaleeros' 'tauste' 'pinsoro' 'farasdues' 'cariñena'] ['ejea de los caballeros' 'san juan de mozarrifar' 'sta. anastasia' 'el sabinar' 'zaragoza' 'bayo (el)' 'bardenas' 'valareña' 'tauste' 'pinsoro' 'farasdues' 'cariñena']
  • 125. Corregir correlaciones erróneas entre atributosCorregir correlaciones erróneas entre atributos Hay muchos atributos en los que dado un valor del atributo el otro está determinado. Por ejempo codigo postal y municipio. Es interesante detectar todas las situaciones en las que eso no ocurre, ya que seguramente sean errores. In [14]: resumen = pac.groupby('solicitante código postal')['solicitante localidad'].nuniqu e() for cp in resumen.loc[50800:50899].index: if resumen.loc[cp] != 1: filtro = pac['solicitante código postal'] == cp print("Código {} Veces {}".format(cp, pac[filtro]['solicitante localidad'] .unique())) In [15]: cp50840 = pac['solicitante código postal'] == 50840 pac.loc[cp50840, 'solicitante localidad'] = 'san mateo de gállego' print(pac[cp50840]['solicitante localidad'].unique()) Código 50800 Veces ['zuera' 'zuuera' nan] Código 50810 Veces ['ontinar de salz' 'ontinar del salz' 'zuera'] Código 50820 Veces ['san juan de mozarrifar' 'zaragoza'] Código 50830 Veces ['lomas gallego' 'villanueva de gállego' 'zaragoza' 'villanueva de gallego'] Código 50840 Veces ['san mateo de gallego' 'san mateo de gállego' 'san ateo de gallego' 'san mateo gallego'] Código 50850 Veces ['santa eulalia de gallego' 'moran'] ['san mateo de gállego']
  • 126. Ejercicio de EstandarizaciónEjercicio de Estandarización Corrige errores de estandarización de "san mateo de gallego" y de las fechas de "solicitud fecha". In [16]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 127. Pulsa aqui para ver la solución
  • 128. NormalizaciónNormalización Es el proceso por el que se transforman valores de variables a rangos similares. Operaciones típicas de normalización: centrar (p.e. media = 0) escalar (p.g. rango 0..1, o -0.5..0.5) pac['colnum'] = pac['colnum']/pac['colnum'].max()-0.5
  • 129. Vamos a cambiar el año de nacimiento por su edad. In [17]: pac['edad'] = 2019 - pac['solicitante año nacimiento'] pac.head(5) Out[17]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solicitan esta ci 0 2018 22 1 1 2018- 05-15 29/05/2018 0:00 22 130 bernues 22711 1995 SO 1 2018 22 1 2 2018- 10-05 30/05/2018 0:00 22 130 jaca 22700 1967 CA 2 2018 22 1 3 2018- 01-03 01/03/2018 0:00 22 130 jaca 22700 1955 SO 3 2018 22 1 4 2018- 01-03 01/03/2018 0:00 22 76 biniés 22773 1947 CA 4 2018 22 1 5 2018- 02-03 02/03/2018 0:00 22 76 biniés 22773 1947 SO
  • 130. Reclasi caciónReclasi cación Agrupar variables numéricas continuas en nuevas categorias por rangos de valores. Por ejemplo, clasi!car los solicitantes en primera edad , segunda edad , tercera edad y cuarta edad
  • 131. Los valores se pueden visualizar de forma grá!ca agrupados por rangos. In [19]: %matplotlib inline import matplotlib as plt from matplotlib import pyplot plt.pyplot.hist(pac["edad"]) plt.pyplot.xlabel("edad") plt.pyplot.ylabel("ocurrencias") plt.pyplot.title("Agrupación por edad") Out[19]: Text(0.5, 1.0, 'Agrupación por edad')
  • 132. Si los rangos de ocurrencias son muy dispares, no se ven bien los resultados. Esto se puede corregir usando una escala logaritmica en el eje y . In [20]: %matplotlib inline import matplotlib as plt from matplotlib import pyplot plt.pyplot.yscale("log") plt.pyplot.hist(pac["edad"]) plt.pyplot.xlabel("edad") plt.pyplot.ylabel("ocurrencias") plt.pyplot.title("Agrupación por edad") Out[20]: Text(0.5, 1.0, 'Agrupación por edad')
  • 133. Ejercicio de VisualizaciónEjercicio de Visualización Visualiza las categorias de la columna catEdadVisualiza las categorias de la columna catEdad In [21]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 134. Pulsa aqui para ver la solución
  • 135. Finalizamos salvando los datos limpios para utilizarlos más adelante: In [22]: pac.to_csv('datos/ayudasPAC2018_Hora5.csv', sep = ";", quoting = csv.QUOTE_ALL, quotechar = '"', index = False)
  • 136. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Alternativamente, cargamos el !chero de un directorio de nuestro disco In [3]: import pandas as pd pd.set_option('display.max_columns', None) pac = pd.read_csv('datos/ayudasPAC2018.csv', sep=';', # Separados por punto y coma quotechar='"' # Delimitados por comillas dobles ) pac.head() Out[3]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CESTAD 0 2018 22 1 1 15/05/2018 13:48 29/05/2018 0:00 22 130 BERNUES 22711 1995 SO 1 2018 22 1 2 10/05/2018 20:17 30/05/2018 0:00 22 130 JACA 22700 1967 CA 2 2018 22 1 3 01/03/2018 9:38 01/03/2018 0:00 22 130 JACA 22700 1955 SO 3 2018 22 1 4 01/03/2018 12:58 01/03/2018 0:00 22 76 BINIÉS 22773 1947 CA 4 2018 22 1 5 02/03/2018 11:50 02/03/2018 0:00 22 76 BINIÉS 22773 1947 SO
  • 137. Análisis y visualización de datos: Procesos usados para analizar el contenido de los datos y extraer información relevante de forma analítica y visual. Tabla de contenidosTabla de contenidos Correlaciones y su visualización Análisis estadístico y su visualización
  • 138. Primero vamos a cargar los datos limpios de la hora anterior In [1]: import pandas as pd pac = pd.read_csv('datos/ayudasPAC2018_Hora5.csv', sep=';', quotechar='"') pac.head(5) Out[1]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solicitan esta ci 0 2018 22 1 1 2018- 05-15 29/05/2018 0:00 22 130 bernues 22711 1995 SO 1 2018 22 1 2 2018- 10-05 30/05/2018 0:00 22 130 jaca 22700 1967 CA 2 2018 22 1 3 2018- 01-03 01/03/2018 0:00 22 130 jaca 22700 1955 SO 3 2018 22 1 4 2018- 01-03 01/03/2018 0:00 22 76 biniés 22773 1947 CA 4 2018 22 1 5 2018- 02-03 02/03/2018 0:00 22 76 biniés 22773 1947 SO
  • 139. CorrelacionesCorrelaciones Identi car correspondencias entre conjuntos de variables numericas es importante para determinar si hay columnas con información redundante (o para detectar que dos columnas que deberían estar correladas no lo están). En nuestro caso, claramente hay correlación entre la edad y el año de nacimiento y entre la provincia y el código postal (que no sea 1.0 implica que hay errores). La solicitud año es NaN ya que solo contiene el valor 2018 y por tanto no se puede calcular la correlación.
  • 140. In [2]: pac.corr() Out[2]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitante código provincia solicitante código municicipio solicitante código postal solicitante año nacimiento número la edad solicitud año NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN solicitud código provincia NaN 1.000000 0.534518 0.016448 0.903922 0.024093 0.904364 -0.056359 0.880337 0.056359 solicitud código agencia NaN 0.534518 1.000000 -0.076022 0.479820 -0.090408 0.477984 -0.026473 0.468282 0.026473 solicitud número relativo NaN 0.016448 -0.076022 1.000000 -0.002218 -0.014590 -0.002513 0.121751 0.153837 -0.121751 solicitante código provincia NaN 0.903922 0.479820 -0.002218 1.000000 0.043176 0.998688 -0.049896 0.807439 0.049896 solicitante código municicipio NaN 0.024093 -0.090408 -0.014590 0.043176 1.000000 0.041328 -0.002142 0.031204 0.002142 solicitante código postal NaN 0.904364 0.477984 -0.002513 0.998688 0.041328 1.000000 -0.049312 0.806047 0.049312 solicitante año nacimiento NaN -0.056359 -0.026473 0.121751 -0.049896 -0.002142 -0.049312 1.000000 -0.036377 -1.000000 número !la NaN 0.880337 0.468282 0.153837 0.807439 0.031204 0.806047 -0.036377 1.000000 0.036377 edad NaN 0.056359 0.026473 -0.121751 0.049896 0.002142 0.049312 -1.000000 0.036377 1.000000
  • 141. Las correlaciones se pueden ver como un mapa de colores. Como es complejo, de!namos la función heatmap para reutilizarla. In [3]: import matplotlib.pyplot as plt import seaborn as sns sns.set(rc={'figure.figsize':(12,6)}) def heatmap(c): ax = sns.heatmap(c, vmin=-1, vmax=1, center=0, cmap=sns.diverging_palette(20, 220, n=200),square=True) ax.set_xticklabels(ax.get_xticklabels(), rotation=45,horizontalalignment='righ t');
  • 142. In [4]: %matplotlib inline corr = pac.corr() heatmap(corr)
  • 143. Creación de indicadoresCreación de indicadores No vemos la correlación con las etiquetas textuales y fechas ya que no son números. Se pueden generar indicadores numéricos arti!ciales para poder obtener dichas correlaciones si los valores son controlados. Se crea una columna nueva por valor In [5]: variableTemporal = pd.get_dummies(pac["solicitante sexo"]) variableTemporal.rename(columns={'M':'Hombre', 'V':'Mujer'}, inplace=True) variableTemporal.head() Out[5]: Hombre Mujer 0 0 1 1 0 1 2 0 1 3 0 1 4 0 1
  • 144. Añadimos las nuevas columnas In [6]: pac = pd.concat([pac, variableTemporal], axis=1) pac.head(5) Out[6]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante código postal solicitante año nacimiento solicitan esta ci 0 2018 22 1 1 2018- 05-15 29/05/2018 0:00 22 130 bernues 22711 1995 SO 1 2018 22 1 2 2018- 10-05 30/05/2018 0:00 22 130 jaca 22700 1967 CA 2 2018 22 1 3 2018- 01-03 01/03/2018 0:00 22 130 jaca 22700 1955 SO 3 2018 22 1 4 2018- 01-03 01/03/2018 0:00 22 76 biniés 22773 1947 CA 4 2018 22 1 5 2018- 02-03 02/03/2018 0:00 22 76 biniés 22773 1947 SO
  • 145. Obtención de correlacionesObtención de correlaciones Volvemos a calcular la correlación. In [7]: heatmap(pac.corr())
  • 146. Si nos interesa conocer si los datos observados son consistentes con una correlación hay que calcular el p-value. Si p-value está entre 0.0 y 0.05 se considera que hay evidencia estadística de dicha correlación. In [8]: from scipy import stats pearson_coef, p_value = stats.pearsonr(pac['solicitante código provincia'], pac['solicitante código postal']) print("El coeficiente de correlación de Pearson es {0:.8f} con un p-value de {1}" .format(pearson_coef, p_value)) El coeficiente de correlación de Pearson es 0.99868782 con un p-value de 0.0
  • 147. Ejercicio de calculo de correlacionesEjercicio de calculo de correlaciones Calcula la correlación entre divorciados con el solicitante código postal con suCalcula la correlación entre divorciados con el solicitante código postal con su p-valuep-value In [9]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 148. Pulsa aqui para ver la solución
  • 149. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Obtenemos las dimensiones del conjunto de datos In [4]: print(pac.shape) Así que vemos que hay 44980 !las y 15 columnas. (44980, 14)
  • 150. También podemos visualizar las correlaciones entre columnas sin relación para ver su distribución. In [11]: sns.regplot(x="solicitud código provincia", y="edad", data=pac) Out[11]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1e9ee910>
  • 151. En este caso quizás es mejor usar un violinplot . Veamos ahora In [12]: sns.violinplot(x="solicitud código provincia", y="edad", data=pac) Out[12]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1dade9d0>
  • 152. El análisis de correlaciones nos pueden mostrar caracteristicas tipicas en los datos. Por ejemplo que las solicitudes de la PAC no se realizan en su mayoria en la provincia del solitante. In [13]: sns.violinplot(x="solicitud código provincia", y="solicitante código provincia", data=pac) Out[13]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1d6c21d0>
  • 153. Si los valores a analizar son rangos hay herramientas de visualización más informativas. Es mejor usar un boxplot que muestra la dispersión de los valores respecto de las categorías.
  • 154. Si analizamos el estado civil respecto de la edad que en general los agricultores de unos 50 años y los viudos pasan los 75. In [14]: pac = pac.sort_values(by=['solicitante estado civil']) sns.boxplot(x="solicitante estado civil", y="edad", data=pac) Out[14]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1d7426d0>
  • 155. Pero si combinamos información con otras grá!cas las conclusiones son sorprendentes In [15]: sns.violinplot(x="solicitante estado civil", y="edad", data=pac) Out[15]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1e393810>
  • 156. Podemos combinar los pares de propiedades que nos interese visualizar, mientras el eje Y sea numérico. In [16]: sns.boxplot(x="solicitante sexo", y="edad", data=pac) Out[16]: <matplotlib.axes._subplots.AxesSubplot at 0x1a1da423d0>
  • 157. Ejercicio de visualización de distribucionesEjercicio de visualización de distribuciones Muestra la edad por estado civil del solicitante, en dos tablas por mujeres yMuestra la edad por estado civil del solicitante, en dos tablas por mujeres y por hombrespor hombres In [17]: #### Inicio del programa a desarrollar (listado hombres) #### Escribe tu código a continuación #### Fin del programa a desarrollar In [18]: #### Inicio del programa a desarrollar (listado mujeres) #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 158. Siguientes pasosSiguientes pasos Ahora habría que explorar los datos para: Comprender su contenido Evaluar su calidad Descubrir cualquier información preliminar relevante Determinar si hay que completar la información
  • 159. Analisis estadístico descriptivoAnalisis estadístico descriptivo Conteo de valores en una columna Obtención de media y desviación Cálculo de mínimos, máximos y cuartiles Agrupaciones
  • 160. Analisis de las características de los datosAnalisis de las características de los datos Ya vimos en una hora anterior como sacar medidas estadisticas básicas de los datos numéricos. In [19]: pac.describe() Out[19]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitante código provincia solicitante código municicipio solicitante código postal solicitante año nacimiento núm count 44941.0 44941.000000 44941.000000 44941.000000 44941.000000 44941.000000 44941.000000 44941.000000 44941.0 mean 2018.0 39.574509 23.410516 615.720478 39.676264 153.212545 40055.464787 1958.073430 22489.9 std 0.0 12.454853 12.361782 471.941781 12.624944 132.294441 12640.013129 14.505546 12986.0 min 2018.0 22.000000 1.000000 1.000000 1.000000 1.000000 1010.000000 1835.000000 1.00000 25% 2018.0 22.000000 13.000000 237.000000 22.000000 61.000000 22550.000000 1948.000000 11242.0 50% 2018.0 44.000000 23.000000 511.000000 44.000000 128.000000 44621.000000 1958.000000 22494.0 75% 2018.0 50.000000 32.000000 894.000000 50.000000 222.000000 50341.000000 1967.000000 33734.0 max 2018.0 50.000000 48.000000 4004.000000 50.000000 912.000000 55687.000000 2014.000000 44980.0
  • 161. También se puede con los datos no numéricos. In [20]: pac.describe(include=['object']) Out[20]: solicitud registro solicitud fecha solicitante localidad solicitante estado civil solicitante sexo catEdad count 44941 44941 44914 44941 39997 44941 unique 106 107 2344 5 2 4 top 2018-05-14 31/05/2018 0:00 zaragoza CA V Segunda edad freq 2119 1864 3394 29975 28224 29553
  • 162. AgrupacionesAgrupaciones Puede ser interesante obtener medias u otras medidas de subconjuntos agrupados de columnas In [21]: agrupacion=pac[['solicitante estado civil','edad']] agrupacion=agrupacion.groupby(['solicitante estado civil'],as_index = False).mean () agrupacion.head() Out[21]: solicitante estado civil edad 0 CA 62.054679 1 DI 55.423810 2 SJ 59.627409 3 SO 51.336640 4 VI 78.198285
  • 163. Se pueden hacer agrupaciones por múltiples atributos. Cuando hay agrupaciones de múltiples atributos es mas claro visualizarlo como tabla agrupada ( pivot ) In [22]: agrupacion=pac[['solicitante estado civil','solicitante sexo','edad']] agrupacion=agrupacion.groupby(['solicitante estado civil', 'solicitante sexo'],as_ index= False).mean() pivote=agrupacion.pivot(index='solicitante estado civil',columns='solicitante sex o') pivote Out[22]: edad solicitante sexo M V solicitante estado civil CA 60.848381 62.889959 DI 58.414894 54.561350 SJ 60.543478 59.317212 SO 51.029590 51.381119 VI 77.734702 79.162072
  • 164. La información de la agrupación también se puede mostrar como un mapa de colores (es este caso no es muy claro) In [23]: plt.pcolor(pivote, cmap='RdBu') plt.colorbar() plt.show()
  • 165. Ejercicio de agrupacionesEjercicio de agrupaciones Crea una agrupación que muestre la media de edad por provincia delCrea una agrupación que muestre la media de edad por provincia del solicitante y sexosolicitante y sexo In [24]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 166. Pulsa aqui para ver la solución
  • 167. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Veamos que información disponemos: In [5]: # Muestra todos los valores únicos en la columna DLOCAL print("DLOCAL contiene", pac['DLOCAL'].unique().size, "valores distintos:") print(pac['DLOCAL'].unique()) # Muestra todos los valores únicos en la columna CESTADO print("CESTADO contiene", pac['CESTADO'].unique().size, "valores distintos:") print(pac['CESTADO'].unique()) ¿Qué problema tiene este conjunto de datos? Conclusión: Comprender el dato implica comprender los problemas que puede tener DLOCAL contiene 2935 valores distintos: ['BERNUES' 'JACA' 'BINIÉS' ... 'ANENTO' 'Villadoz' 'Villar de los Navarros'] CESTADO contiene 6 valores distintos: ['SO' 'CA' 'VI' 'None' 'DI' 'SJ']
  • 168. Modelos de predicción: Conjunto de técnicas matemáticas para crear modelos que permitan predecir el valor de una variable en función de otras. Tabla de contenidosTabla de contenidos Regresión lineal Regresión lineal multiple Modelos no lineales
  • 169. El uso de modelos de predicción implica la existencia de tres tipos de colecciones de datos: Colección de entrenamiento: Conjunto de datos donde están de!nidos los pares de variables independientes, variable dependiente que desearemos predecir y que se usa para entrenar el modelo. Colección de pruebas: Colección equivalente a la de entrenamiento. Son datos que el modelo no ha usado al entrenarse y permite calcular la calidad en un contexto más cercano al real. Datos reales: Conjunto de variables independientes para las cuales no se dispone la variable dependiente y queremos calcularla. Son el objetivo de nuestro modelo.
  • 170. Colección de trabajoColección de trabajo Para esta hora vamos a trabajar con una colección de producción de maíz en Estados Unidos. Por tanto vamos a cargarla, analizarla y prepararla tal y como hemos visto en las horas anteriores. In [1]: import pandas as pd import numpy as np maiz = pd.read_csv('datos/prodMaizUSA.csv', sep=';') In [2]: maiz.head(10) Out[2]: Año Acres plantados (Millones) Acres recolectados (Millones) Produccion (Millones de fanegas) Producción por acre recolectado (Fanegas por acre) Precio por fanega (dolares) 0 1926 99.66 83.28 2140.21 25.7 0.72 1 1927 98.46 83.92 2218.19 26.4 0.80 2 1928 100.40 85.83 2260.99 26.3 0.80 3 1929 99.13 83.19 2135.04 25.7 0.76 4 1930 103.92 85.53 1757.30 20.5 0.55 5 1931 109.36 91.13 2229.90 24.5 0.29 6 1932 113.02 97.21 2578.69 26.5 0.29 7 1933 109.83 92.13 2104.73 22.8 0.49 8 1934 100.56 61.25 1146.73 18.7 0.80 9 1935 99.97 82.55 2001.37 24.2 0.63
  • 171. Los datos estan limpios a excepción de las cabeceras que son muy largas y los años que salen como reales. In [3]: cabeceras = ['año','acres plant','acres rec','producción','producción acre', 'prec io'] maiz.columns = cabeceras maiz['año'].astype(int) maiz.head() Out[3]: año acres plant acres rec producción producción acre precio 0 1926 99.66 83.28 2140.21 25.7 0.72 1 1927 98.46 83.92 2218.19 26.4 0.80 2 1928 100.40 85.83 2260.99 26.3 0.80 3 1929 99.13 83.19 2135.04 25.7 0.76 4 1930 103.92 85.53 1757.30 20.5 0.55
  • 172. Observamos las correlaciones entre columnas. In [4]: maiz.corr() Out[4]: año acres plant acres rec producción producción acre precio año 1.000000 -0.409857 -0.161847 0.943515 0.975485 0.800730 acres plant -0.409857 1.000000 0.904342 -0.151488 -0.337265 -0.089667 acres rec -0.161847 0.904342 1.000000 0.112375 -0.082410 0.105670 producción 0.943515 -0.151488 0.112375 1.000000 0.976388 0.788431 producción acre 0.975485 -0.337265 -0.082410 0.976388 1.000000 0.741430 precio 0.800730 -0.089667 0.105670 0.788431 0.741430 1.000000
  • 173. Hay correlación entre el año y la producción y entre la producción y el precio. No parece haber mucha correlacion entre los acres plantados In [5]: import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline corr = maiz.corr() ax = sns.heatmap(corr, vmin=-1, vmax=1, center=0,cmap=sns.diverging_palette(20, 22 0, n=200),square=True) ax.set_xticklabels(ax.get_xticklabels(),rotation=45,horizontalalignment='right');
  • 174. Vamos a analizar los p-value de las columnas con correlación para ver si la correlación es signi!cativa In [6]: from scipy import stats res = stats.pearsonr(maiz['producción'], maiz['precio']) print("Producción-Precio Pearson es {0:.6f} con un P-value de = {1:.2f}".format(*r es)) res = stats.pearsonr(maiz['producción acre'], maiz['precio']) print("ProducciónAcre-Precio Pearson es {0:.6f} con un P-value de = {1:.2f}".forma t(*res)) res = stats.pearsonr(maiz['año'], maiz['precio']) print("Año-Precio Pearson es {0:.6f} con un P-value de = {1:.2f}".format(*res)) Producción-Precio Pearson es 0.788431 con un P-value de = 0.00 ProducciónAcre-Precio Pearson es 0.741430 con un P-value de = 0.00 Año-Precio Pearson es 0.800730 con un P-value de = 0.00
  • 175. Regresión linealRegresión lineal La regresión lineal es un metodo que a partir de una colección de datos, nos permite deducir la relación entre dos variables. Dicha relación se expresa mediante una ecuación lineal. En esta ecuación X es el predictor (variable independiente), Y es la predicción (variable dependiente), y a y b son los parámetros lineales que permiten predecir el resultado. Ŵ ŶƂ Ŷ ŷų
  • 176. Para elegir qué variable es más apropiada para construir un modelo de regresión lineal podemos observar gra!camente la relación entre los pares de variables. In [7]: maiz.plot.scatter(x='producción', y='precio') Out[7]: matplotlib.axes._subplots.AxesSubplot at 0x1ca6dc56348
  • 177. In [8]: maiz.plot.scatter(x='producción acre', y='precio') Out[8]: matplotlib.axes._subplots.AxesSubplot at 0x1ca6ec93208
  • 178. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Vamos a arreglar algunos de los problemas. Podemos normalizar valores Hay nombres de municipios en mayusculas y otros en minúsculas In [6]: pac['DLOCAL'] = pac['DLOCAL'].str.lower() print(DLOCAL contiene, pac['DLOCAL'].unique().size, valores distintos:) El número de localidades se reduce de 2935 a 2360 si ignoramos las mayúsculas y las minúsculas. DLOCAL contiene 2360 valores distintos:
  • 179. A la hora de realizar la predicción, necesitamos calcular una medida que nos indique lo bien o mal que está hecha la predicción. Las dos mas habituales son el Coe!ciente de determinación R-Cuadrado y el Error Cuadrático Medio. El R-Cuadrado indica la proporción de la varianza total de la variable explicada por la regresión. Es decir la parte de la información capturada por la regresión (más alto mejor). El error cuadrático medio mide la diferencia entre el valor actual y el predecido (más pequeño mejor).
  • 180. Para de!nir una regresion creamos el modelo y lo ajustamos ( fit ) con la propiedad explicativa y la propiedad de respuesta. Una vez hecha la predicción podemos comprobar su R-cuadrado y su error cuadratico Medio In [10]: from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error lm = LinearRegression() X = maiz[['producción acre']] Y = maiz['precio'] lm.fit(X,Y) Yhat=lm.predict(X) print(Yhat[0:5]) print(Y[0:5].array) print(R-Cuadrado,lm.score(X, Y)) print(Error cuadratico medio, mean_squared_error(Yhat, Y)) [0.79089373 0.80472425 0.80274846 0.79089373 0.68815276] PandasArray [0.72, 0.8, 0.8, 0.76, 0.55] Length: 5, dtype: float64 R-Cuadrado 0.5497178111755494 Error cuadratico medio 0.6738019115783881
  • 181. Podemos obtener los parametros de la función lineal In [11]: print(a:,lm.intercept_) print(b:,lm.coef_) a: 0.2831162284334352 b: [0.01975788]
  • 182. Podemos visualizar los datos originales con los predichos para ver como se ajusta la predicción In [12]: plt.plot(X, Y, 'o', color='blue'); plt.plot(X, Yhat, 'o', color='red'); Asi pues el precio se puede aproximar a: 0.28 + 0.019*produccion acre
  • 183. Se puede visualizar la linea de la regresión superpuesta con los datos y con indicadores de varianza de los datos usando regplot . In [13]: sns.regplot(maiz['producción acre'], maiz['precio'],data=maiz) Out[13]: matplotlib.axes._subplots.AxesSubplot at 0x1ca6f186e88
  • 184. También podemos visualizar la diferencia entre la predicción y el valor real para identi!car si el modelo lineal nos sirve como predictor con residplot . In [14]: sns.residplot(maiz['producción acre'], maiz['precio']) Out[14]: matplotlib.axes._subplots.AxesSubplot at 0x1ca6f200a88
  • 185. Ejercicio de regresión linealEjercicio de regresión lineal Calcula un modelo de regresión lineal en función del año y obten su errorCalcula un modelo de regresión lineal en función del año y obten su error cuadraticocuadratico Calcula un modelo de regresión lineal en función de la producción y obten suCalcula un modelo de regresión lineal en función de la producción y obten su error cuadraticoerror cuadratico ¿Cuál es el mejor estimador y cuales son sus parametros?¿Cuál es el mejor estimador y cuales son sus parametros? In [ ]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 186. Pulsa aqui para ver la solución
  • 187. Regresión lineal multipleRegresión lineal multiple Puede que una sola de las columna de los no sea su!ciente para predecir el precio. Podemos de!nir un modelo que conbine linealmente toda la información para obtener una predicción mejor Ŵ ŶƂ Ŷ ŷų ŷų ŷų ŷų In [15]: Z = maiz[['producción acre', 'año']] lm = LinearRegression() lm.fit(Z, maiz['precio']) Yhat= lm.predict(Z) print(R-Cuadrado,lm.score(Z, Y)) print(Error cuadratico medio año, mean_squared_error(Y, Yhat)) print(a:,lm.intercept_) print(b:,lm.coef_) R-Cuadrado 0.6736628430623427 Error cuadratico medio año 0.4883306637948677 a: -144.72542454604985 b: [-0.02182851 0.07532843]
  • 188. Si visualizamos la predicción comparada con los valores originales In [16]: plt.plot(X, Y, 'o', color='blue'); plt.plot(X, Yhat, 'o', color='red');
  • 189. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Podemos localizar casos raros Podemos ver lon nombres que sólo pasan una vez In [7]: unicos = pac['DLOCAL'].value_counts() == 1 valores = sorted(unicos[unicos].index.values) print(len(valores)) valores[:10] # Devuelve los 10 primeros Out[7]: 843 [' portellada, la ', '192', '22520', 'abadiño', 'abenfigo', 'abenfigo- castellote', 'ademuz', 'agramunt', 'aguatón', 'aguilar']
  • 190. Ejercicio de regresión lineal multipleEjercicio de regresión lineal multiple Crea un modelo de regresión lineal multiple que utilice como entrada laCrea un modelo de regresión lineal multiple que utilice como entrada la producción, la producción por acre recolectado y el año para calcular el precio.producción, la producción por acre recolectado y el año para calcular el precio. Muestra gra!camente la comparativa del resultado con los datos originales.Muestra gra!camente la comparativa del resultado con los datos originales. In [ ]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 191. Pulsa aqui para ver la solución
  • 192. Modelos no linealesModelos no lineales Igual que existen modelos de regresión lineales hay modelos que usan ecuaciones polinómicas. El problema de estos modelos es identi!car el polinómio más adecuado para ajustar los datos. Las redes neuronales son otra alternativa para de!nir modelos de ajuste no lineales. Son complicadas de con!gurar, ya que tienen muchos hiperparametros (neuronas, capas, algorimo de optimización, ecuación de calculo del error, etc). Sin embargo, con datos de entrenamiento su!cientes generan muy buenos resultados. In [ ]: #import sys #!conda install --yes --prefix {sys.prefix} keras La sigiente red toma como entrada todas las columnas de la tabla menos el precio y las usa para aprender a predecir el precio. Tiene 2 capas: una entrada 10 neuronas conectadas con las entradas, y una salida de 1 neurona que predice el precio.
  • 193. In [18]: import warnings warnings.filterwarnings('ignore') # Desactivamos warnings en Jupyter import tensorflow as tf tf.get_logger().setLevel('ERROR') # Desactivamos warnings en TensorFlow from keras.models import Sequential from keras.layers import Dense, Dropout from keras.optimizers import Adam import numpy as np dataset = maiz[['año','acres plant','acres rec','producción','producción acre', 'p recio']].to_numpy() np.random.seed(10) np.random.shuffle(dataset) X = dataset[:,0:5] Y = dataset[:,5:6] model = Sequential() model.add(Dense(10, kernel_initializer='normal', input_shape=(5,), activation='re lu')) model.add(Dense(1, activation='linear')) model.compile(optimizer=Adam(lr=0.001), loss='mean_squared_error') model.fit(X, Y, epochs=10001, verbose=0) Out[18]: Using TensorFlow backend. keras.callbacks.History at 0x1ca75cf9908
  • 194. Una vez entrenado el modelo, podemos hacer predicciones con el. Comparamos los valores con el error cuadrático medio y la diferencia entre las distribuciones. In [19]: prediction = model.predict(X) print(mean_squared_error(prediction, Y)) ax1 = sns.distplot(Y, hist=False, color=r, label=Valor Real) sns.distplot(prediction, hist=False, color=b, label=Valor Estimado , ax=ax1) plt.title('Valor real vs estimado') plt.xlabel('Precio') plt.ylabel('Proporción de años') Out[19]: 0.3814094695648771 Text(0, 0.5, 'Proporción de años')
  • 195. Visualización espacial de datosVisualización espacial de datos
  • 196. Visualización espacial de datos: Procesos usados para la creación de mapas con diversos objetivos. Tabla de contenidosTabla de contenidos Introducción a Folium Mapas con marcadores GeoJSON y Folium Coropletas con Folium Conclusión de las Jornadas
  • 197. Introducción a FoliumIntroducción a Folium Folium es una librería de Python que ayuda a crear mapas con Lea et. Los mapas creados pueden verse embebidos en el notebook, pero se pueden exportar para ser embebidos en páginas web. Folium soporta OpenStreetMap, Mapbox, Statmen, GeoJSON, TopoJSON, ... In [1]: #!conda install -c conda-forge folium import folium
  • 198. Un mapa mundial en FoliumUn mapa mundial en Folium Es bastante trivial In [2]: folium.Map() Out[2]: + − Leaflet (https://leafletjs.com) | Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
  • 199. Ahora un mapa más interesanteAhora un mapa más interesante In [3]: folium.Map(location=[41.6523, -0.8940], zoom_start=18) Out[3]: ++ − Leaflet (https://leafletjs.com) | Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
  • 200. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Podemos modi!car los datos de forma masiva Podemos eliminar los espacios que hay antes y después In [8]: pac['DLOCAL'] = pac['DLOCAL'].str.strip() unicos = pac['DLOCAL'].value_counts() == 1 valores = sorted(unicos[unicos].index.values) len(valores) Out[8]: 823
  • 201. Pulsa aqui para ver la solución
  • 202. Con gurar estilo de visualizaciónCon gurar estilo de visualización Folium puede generar mapas con diferentes estilos además de OpenStreetMap. Stamen Toner es un estilo de mapa de alto contraste mientras que Stamen Terrain es más realista.
  • 203. In [5]: folium.Map(location=[41.6563,-0.8811], zoom_start=8, tiles='Stamen Toner') Out[5]: ++ − Leaflet (https://leafletjs.com) | Map tiles by Stamen Design (http://stamen.com), under CC BY 3.0 (http://creativecommons.org/licenses/by/3.0). Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
  • 204. In [6]: folium.Map(location=[41.6563,-0.8811], zoom_start=8, tiles='Stamen Terrain') Out[6]: ++ − Leaflet (https://leafletjs.com) | Map tiles by Stamen Design (http://stamen.com), under CC BY 3.0 (http://creativecommons.org/licenses/by/3.0). Data by © OpenStreetMap (http://openstreetmap.org), under CC BY SA (http://creativecommons.org/licenses/by-sa/3.0).
  • 205. Mapas con marcadoresMapas con marcadores Vamos a crear un mapa que muestre las localidades de zaragoza In [7]: import pandas as pd entidades = pd.read_csv('datos/entidades.csv', sep=';', decimal=',') entidades.columns = ['Provincia', 'Comarca', 'Clasificación', 'Código INE', 'Denom inación', 'Longitud', 'Latitud'] nucleos_zgz = entidades[(entidades['Provincia'] == 'Zaragoza') (entidades['Clasificación'] == '3.- Núcleo')] nucleos_zgz.shape Ahora en entidades_zgz tenemos 436 núcleos de población. Out[7]: (436, 7)
  • 206. Procedemos a crear un mapa y visualizarlo In [8]: zaragoza = folium.Map(location=[41.6563, -0.8811], zoom_start=7) localidades = folium.map.FeatureGroup() for lat, lng, in zip(nucleos_zgz.Latitud, nucleos_zgz.Longitud): localidades.add_child( folium.CircleMarker( [lat, lng], radius=5, color='yellow', fill=True, fill_color='blue', fill_opacity=0.6) )
  • 207. In [9]: zaragoza.add_child(localidades) Out[9]: ++ − Leaflet (https://leafletjs.com) | Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
  • 208. Pero si queremos etiquetas usaremos marcadores In [10]: zaragoza = folium.Map(location=[41.6563, -0.8811], zoom_start=7) tupla = zip(nucleos_zgz.Latitud, nucleos_zgz.Longitud, nucleos_zgz.Denominación) for lat, lng, label in tupla: folium.Marker( [lat, lng], popup=label).add_to(zaragoza)
  • 209. In [11]: zaragoza Out[11]: ++ − Leaflet (https://leafletjs.com) | Data by © OpenStreetMap (http://openstreetmap.org), under ODbL (http://www.openstreetmap.org/copyright).
  • 210. Pero todavía vemos que hay demasiada información, necesitamos clusters In [12]: from folium import plugins zaragoza = folium.Map(location=[41.6563, -0.8811], zoom_start=7) zaragoza_cluster = plugins. MarkerCluster().add_to(zaragoza) tupla = zip(nucleos_zgz.Latitud, nucleos_zgz.Longitud, nucleos_zgz.Denominación) for lat, lng, label in tupla: folium.Marker([lat, lng], icon=None, popup=label). add_to(zaragoza_cluster)
  • 211. Ejemplo: Procesar ayudas PAC 2018Ejemplo: Procesar ayudas PAC 2018 Podemos modi!car los datos de forma condicionada Podemos resolver un problema que hay con Ejea de los Caballeros In [9]: print(Ocurrencias de 'ejea de los caballeros',len(pac[pac['DLOCAL'].str.contains ('ejea')])) print(Ocurrencias de la palabra 'caballeros',len(pac[pac['DLOCAL'].str.contains( 'caballeros')])) filtro = ~pac['DLOCAL'].str.contains('caballeros') pac['DLOCAL'].str.contains('e jea') pac[filtro].head() In [10]: pac.loc[filtro,'DLOCAL'] = 'ejea de los caballeros' #Cambia en la columna DLOCAL t odas las filas seleccionadas a ejea de los caballeros Out[9]: CCOSEC CPROVI CAGENC CCORRE FREGIS FSOLIC CPRODO CMUNDO DLOCAL CPOSDO CANONAC CES 24320 2018 50 6 45 08/03/2018 16:52 08/03/2018 0:00 50 95 ejea de los c 50600 1963 VI 25248 2018 50 7 186 21/03/2018 8:56 21/03/2018 0:00 50 95 ejea 50694 1954 CA 25637 2018 50 7 576 11/04/2018 10:09 11/04/2018 0:00 50 95 ejea 50600 1942 CA 25638 2018 50 7 577 11/04/2018 10:11 11/04/2018 0:00 50 95 ejea 50600 1969 CA 25762 2018 50 7 702 25/04/2018 8:50 25/04/2018 0:00 50 95 ejea 50600 1966 VI Ocurrencias de 'ejea de los caballeros' 614 Ocurrencias de la palabra 'caballeros' 602
  • 212. EjercicioEjercicio Crear un mapa con los Municipios de aragón de alto contraste.Crear un mapa con los Municipios de aragón de alto contraste. Indicad si es posible la comarca pero que quede bonito.Indicad si es posible la comarca pero que quede bonito. In [14]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 213. Pulsa aqui para ver la solución
  • 214. GeoJSON y FoliumGeoJSON y Folium Es muy fácil usar GeoJSON pero el resultado es muy pesado para verlo en jupyter. Pero se puede salvar: codigos_postales_zaragoza_Hora8.html (datos/codigos_postales_zaragoza_Hora8.html) In [15]: codigos_postales_geo = 'datos/ZARAGOZA.geojson' zaragoza = folium.Map(location=[41.6563,-0.8811], zoom_start=9) def estilo(feature): return { 'fillColor': '#ffff00', 'color': 'black', 'weight': 2, 'dashArray': '5, 5' } folium.GeoJson( codigos_postales_geo, style_function=estilo ).add_to(zaragoza) zaragoza.save('datos/codigos_postales_zaragoza_Hora8.html')
  • 215. Coropletas con FoliumCoropletas con Folium Folium permite crear coropletas de una forma muy !exible. Primero debemos crear un diccionario que contenga una clave y el valor que queremos representar. In [16]: import pandas as pd pac = pd.read_csv('datos/ayudasPAC2018_Hora5.csv', sep=';', quotechar='') pac = pac[pac['solicitante código provincia'] == 50] pac_cp = pac.groupby('solicitante código postal').count() pcap_cp_dict = pac_cp['solicitud año'].to_dict() pac_cp.head() Out[16]: solicitud año solicitud código provincia solicitud código agencia solicitud número relativo solicitud registro solicitud fecha solicitante código provincia solicitante código municicipio solicitante localidad solicitante año nacimiento solicitante estado civil so solicitante código postal 5005 1 1 1 1 1 1 1 1 1 1 1 1 5083 1 1 1 1 1 1 1 1 1 1 1 1 20580 1 1 1 1 1 1 1 1 1 1 1 1 22806 2 2 2 2 2 2 2 2 2 2 2 2 22808 6 6 6 6 6 6 6 6 6 6 6 5
  • 216. Después necesitamos una escala de colores. In [17]: from branca.colormap import linear colormap = linear.YlGn_09.scale(pac_cp['solicitud año'].min(), pac_cp['solicitud a ño'].max()) colormap Out[17]: 1 816
  • 217. Ahora viene lo más complejo, asociar a cada valor de 'solicitante código postal' un color. In [18]: color_dict = {key: colormap(pcap_cp_dict[key]) for key in pcap_cp_dict.keys()} Y asegurarse que en función del COD_POSTAL de cada geometría se le de el color adecuado. In [19]: def computarColor(feature): return { 'fillColor' : color_dict.get(int(feature[properties][COD_POSTAL]), '#f fffff'), 'fillOpacity': 1 }
  • 218. El siguiente paso ya lo hemos realizado antes. Además añadimos un control para activar o desactivar la capa. Todo se salva a solicitantes_pac_zaragoza_Hora8.html (datos/solicitantes_pac_zaragoza_Hora8.html) In [20]: codigos_postales_geo = 'datos/ZARAGOZA.geojson' zaragoza = folium.Map(location=[41.6563,-0.8811], zoom_start=9) folium.GeoJson( codigos_postales_geo, name = 'Demandantes PAC', style_function = computarColor ).add_to(zaragoza) folium.LayerControl().add_to(zaragoza) zaragoza.save('datos/solicitantes_pac_zaragoza_Hora8.html')
  • 219. EjercicioEjercicio Estudiar la distribución en Aragón de la edad media de los solicitantes de laEstudiar la distribución en Aragón de la edad media de los solicitantes de la PAC.PAC. Disponemos de GeoJSON de Zaragoza, Huesca y TeruelDisponemos de GeoJSON de Zaragoza, Huesca y Teruel Queremos saber si nos faltan datosQueremos saber si nos faltan datos In [21]: #### Inicio del programa a desarrollar #### Escribe tu código a continuación #### Fin del programa a desarrollar
  • 220. Pulsa aqui para ver la solución
  • 222. RecapitulaciónRecapitulación 1. Introducción al procesamiento de datos 2. Fuentes de datos 3. Introducción a Python/Jupyter 4. Carga de datos y exploración inicial 5. Limpieza y manipulación de datos 6. Análisis y visualización de datos 7. Modelos de datos 8. Visualización espacial de datos
  • 223. Objetivos alcanzadosObjetivos alcanzados ¿Qué hemos hecho? Hemos aprendido los fundamentos para trabajar con datos y portales de datos abiertos. ¿Qué hemos logrado? Habéis obtenido competencias digitales básica para usar datos abiertos y herramientas que mejoren la competitividad, procesos o información en el sector agroalimentario.