Está en la página 1de 24

1.

Objetivos

En este módulo verás

 Python y Data Science.


 Entorno Anaconda.
 I Python Notebook vs Python.
 Jupyter Notebook y entorno.
 Documentación.

2. Introducción

- Introducción al análisis de datos.

Python se ha convertido en el lenguaje de programación más utilizado a la hora de hacer


análisis de datos. Sin embargo, no fue diseñado para ocupar este lugar, sino que evolucionó
naturalmente en este rol.

Fue la comunidad de usuarios la que adoptó al lenguaje y desarrolló el ecosistema de librerías


de análisis de datos que lo llevó a ser el más usado en ciencia de datos y machine learning.

Sin embargo, hay que recordar que Python es un lenguaje de propósito general con
numerosísimas aplicaciones, por lo que está muy lejos de ser un lenguaje limitado al nicho del
análisis de datos. El lenguaje se diseñó para ser fácil de entender y aprender, elegante y
expresivo. Esto hizo que se convirtiera en la primera opción para mucha gente que se
introduce en la programación y ha permitido que profesionales de las más variadas disciplinas
elijan Python para llevar el análisis de datos al siguiente nivel en sus respectivos trabajos.

Según varias estadísticas, es el lenguaje más aprendido de la actualidad.

Este gráfico muestra el porcentaje de preguntas que se realizan por lenguaje en la plataforma
Stackoverflow.
Librerías

Python tiene miles de librerías para las más variadas tareas, lo que permite realizarlas con
relativa facilidad.

En el entorno de análisis de datos, las tres más importantes son las que veremos en este curso:

Numpy, Pandas y Matplotlib.

● Numpy es una librería de cálculo numérico muy potente que forma la base de muchísimas
otras librerías,

● Pandas está diseñada para el análisis y manejo de datos en estructuras tabulares, y

● Matplotlib es la base para realizar gráficos en Python.

Anaconda

Python es open source y puede ser usado y distribuido libremente (otra de sus grandes
ventajas). Es por eso que se ha creado una distribución particular pensada para ciencia de
datos y machine learning: Anaconda.

Esta distribución viene con las librerías más importantes para análisis de datos, junto con un
instalador de paquetes (pensado para manejar las dependencias entre estos paquetes de
manera más efectiva), una interfaz gráfica y algunas aplicaciones como Jupyter Notebook y
Spyder.

La versión individual se puede descargar de esta página:

https://www.anaconda.com/products/individual

Jupyter Notebook

Es un entorno interactivo para trabajar con lenguajes de programación. Es una aplicación web,
por lo que se visualiza en cualquier navegador. Está pensado para articular código ejecutable,

gráficos, texto, tablas, fórmulas, etc. en un solo documento.

Esto hace que sea muy cómodo ver visualizaciones mientras se exploran los datos y que sea
posible usar la misma herramienta tanto para el desarrollo como para la presentación.

El documento está estructurado en celdas que pueden ser de código o de markdown.

Las celdas de código pueden ejecutarse independientemente y el orden en el que fueron


ejecutadas se muestra al lado del In y el resultado de la última expresión, si lo hay, se marca
con Out.
Sin embargo, todo pertenece a la misma sesión y las variables creadas en celdas anteriores
permanecen en la memoria.

Markdown

Las celdas también pueden ser de tipo markdown, un lenguaje de marcado usado para
formatear texto con un código muy simple. Además, soporta código HTML.

- Datos.

Python para

Análisis de Datos

Módulo 01

Python para Análisis de Datos


Datos

¿Qué es un dato?

Un dato es una representación simbólica de algún aspecto de la realidad, que debe ser
adecuado para su comunicación e interpretación.

Los datos pueden ser cuantitativos o cualitativos, es decir que pueden ser representados por
números (y normalmente alguna unidad) en el primer caso, o por palabras que representan
alguna cualidad en el segundo. Por ejemplo, que un film dure 2 horas es un dato cuantitativo y
que una persona lo califique como ‘excelente’ es un dato cualitativo.

Estructura

También se puede diferenciar entre datos estructurados y no estructurados.

Básicamente, entendemos por datos estructurados a aquellos que se encuentran ordenados


por tipo de dato y que son fácilmente accesibles. Ejemplos de este tipo son las bases de datos
relacionales, las planillas de cálculo, los csv, los formularios, etc.

Por su parte, los datos no estructurados son aquellos que carecen de un orden dado por un
esquema predefinido. Esto hace que la información no sea tan fácil de acceder como en los
datos estructurados. Ejemplos son archivos de texto, audio, imágenes, video, etc.

Representación de datos

La memoria de una computadora se constituye en una serie de bits, que sólo pueden
almacenar ceros y unos. Así que, para poder usar una computadora para analizar datos, hay
que representarlos como una combinación de ceros y unos. Es decir, hay que establecer algún
tipo de codificación entre la información que queremos representar y los elementos de la
memoria de la máquina para que sea posible tanto codificarlos, como analizarlos y
decodificarlos.

Así es como surge la necesidad de definir distintos tipos de datos.

Enteros

Usualmente escribimos los números en decimal o base diez, por lo que necesitamos diez
símbolos (del 0 al 9). Pero, como cada bit sólo puede tener uno de dos valores (0 y 1), en una
computadora es necesario representar los números en binario, es decir en base 2.

En este sistema cada posición representa una potencia de 2. Con n bits se pueden representar
2n combinaciones diferentes de ceros y unos, por lo que hay una cantidad máxima de números
que se pueden representar con esa cantidad de bits.

Para representar números enteros sin signo cada posición representa una potencia no
negativa de 2.
Ejemplo

Los bits 1011 pueden representar el número once si trabajamos con enteros sin signo.

Sin embargo, también se puede usar el primer bit para representar el signo del número
usándose 0 para los positivos y 1 para los negativos. En ese caso, los mismos bits
representarían el número -3.

Hay muchas formas de representar a los números enteros. Como vimos, se puede representar
enteros con o sin signo.

Si tenemos n bits para representar números sin signo, podemos cubrir el rango que va de 0 a
2n–1. Pero si esa misma cantidad de bits la usamos para representar números con signo,
podemos cubrir el rango de ±2n-1-1 (el cero se representa dos veces, +0 y -0). Si queremos
representar números por fuera de ese rango, se produce lo que se llama overflow.

Otras variantes para representar números incluyen el big-endian o little-endian, es decir, si el


bit más significativo va al final o al comienzo, y otra codificación llamada complemento a 2 que
no duplica la representación del cero.

Flotantes

Para representar números racionales, con parte decimal, se utiliza lo que se llama
representación de números de coma flotante. Esta representación debe poder manejar
también potencias negativas de 2 (2-1=0.5, 2-2=0.25, 2-3=0.125, etc.).
Se utiliza algo similar a la notación científica, con una parte para representar las cifras
significativas y otra para representar el exponente al que se eleva la base.

Existen flotantes de distinta precisión: simple (32 bits), doble (64 bits) y cuádruple (128 bits).

Texto

Vimos que podemos usar una serie de bits para representar números. Pero también debemos
ser capaces de codificar otros tipos de datos en ceros y unos, por ejemplo, los caracteres de
texto.

Existen muchas codificaciones de caracteres en números binarios, por ejemplo: ASCII, Unicode,
UTF-8, etc. Todas estas codificaciones establecen un mapeo entre caracteres y números
binarios de distinta longitud. ASCII usa 8 bits, pudiendo codificar 256 caracteres y Unicode
utiliza 16 bits alcanzando 65536 caracteres.

hola (01101000 01101111 01101100 01100001 00100000) mundo (01101101 01110101


01101110 01100100 01101111).

Algunos de los caracteres ASCII y su codificación en binario:

Imágenes

Las pantallas muestran imágenes por píxeles, la menor unidad de representación de una
imagen. Cuantos más píxeles, más resolución. Cada pixel está compuesto por tres colores: rojo,
verde y azul. Cada color tiene 28 = 256 intensidades posibles dando un total de 256 3 =
16777216 combinaciones de colores. Por lo tanto para codificar la intensidad de cada color se
utiliza un byte, y cada pixel se representa con 3 bytes.

Para una imagen en blanco y negro se puede usar un bit por pixel y si es en escala de grises su
puede usar un byte por pixel.
Tipos básicos en Python

Python tiene los tipos de dato entero, flotante y complejo. Los enteros son de precisión
ilimitada, lo que significa son creados dinámicamente y con la cantidad de bytes necesarios
para representarlos. Los flotantes son de 64 bits y los complejos tienen parte real e imaginaria
de 64 bits cada una.

Los strings son secuencias inmutables de caracteres Unicode y pueden tener cualquier
longitud. En Python los booleanos son un tipo de dato que hereda de los enteros y que, para
cualquier operación aritmética, tienen los valores False=0 y True=1.

Cada uno de estos tipos de dato tiene un constructor:

int(), float(), complex(), str() y bool().

3. Manejo de objetos

- Objetos.

Objetos y referencia

En Python todo son objetos, en el sentido de la programación orientada a objetos. Incluso las
funciones y las clases son objetos también. Eso permite que cualquier cosa pueda ser
referenciada por una variable. Y decimos referenciada porque, en Python, crear una variable
es crear un nombre con una referencia (puntero) a la dirección de memoria en donde el objeto
se encuentra.

Esta es la razón por la que una variable no está limitada a un tipo de dato en particular (tipado
dinámico) y crear una nueva asignación a otro tipo de dato es simplemente cambiar la
referencia de la variable.

Referencia

Esto implica que muchas variables pueden apuntar al mismo objeto. De hecho, cuando se
ejecuta una expresión del tipo var2 = var1 no se crea una copia del dato sino que se copia la
referencia, por lo que las dos variables apuntan al mismo objeto en la memoria.

Si el tipo de dato es mutable, cualquier cambio que se haga a través de una de las variables va
a ser visto por la otra variable también, como sucede con las listas.
El manejo de la memoria se hace automáticamente. Python tiene lo que se llama garbage
collector, que borra todos los objetos que quedan sin referencia.

En este ejemplo se ve como ambas variables apuntan al mismo objeto en la memoria y las
modificaciones hechas a través de lista1 son visibles para lista2.

Colecciones

Python viene con una variedad de colecciones para agrupar datos en estructuras diferentes.
Tenemos colecciones ordenadas o no ordenadas y colecciones mutables o inmutables.

Las colecciones ordenadas son aquellas que pueden ser indexadas, es decir, que se pueden
usar números enteros para acceder a sus elementos. Son colecciones ordenadas (o secuencias)
las listas, tuplas y strings.

Como colecciones no ordenadas tenemos los diccionarios, sets y frozensets.

Indexación

Colecciones ordenadas: listas, tuplas, strings

La indexación se puede realizar con uno, dos o tres parámetros separados por dos puntos. Con
un parámetro se obtiene un elemento en particular. Se empieza a contar desde cero en
adelante para seleccionar elementos contando desde la izquierda y números negativos para
seleccionar empezando desde la derecha.

Con dos parámetros se puede seleccionar porciones (slices) de la secuencia y el tercer


parámetro indica el paso con el que los elementos deben tomarse.
Las listas son secuencias mutables, se pueden cambiar, agregar o borrar sus elementos. Sin
embargo, las tuplas y los strings son tipos de datos inmutables y una vez creados no se pueden
modificar. A lo sumo, es posible crear nuevas tuplas o strings a partir de los originales.

Los elementos de una lista se pueden cambiar mediante simples asignaciones, se puede
agregar elementos con los métodos append e insert y se puede borrar elementos con los
métodos remove, pop, clear y la palabra reservada del.

Colecciones no ordenadas: diccionarios, sets, frozensets

Las colecciones no ordenadas no soportan la indexación por números enteros ya que no se


puede decir cuál de sus elementos es el primero, segundo, etc.

Los diccionarios son colecciones en donde cada elemento consta de dos partes: una clave y un
valor. Las claves hacen las veces de índice y permiten seleccionar los respectivos valores del
diccionario. Los valores pueden ser cualquier tipo de dato, mientras las claves tienen que ser
obligadamente un tipo de dato inmutable.

Además, las claves no se pueden repetir. Los valores correspondientes a una clave se pueden
modificar y se puede agregar o quitar elementos.

Conjuntos

Los conjuntos son otro tipo de colección no ordenada. Sus elementos, al igual que las claves de
un diccionario, deben ser tipos de dato inmutables. Sus elementos no se pueden repetir. Un
objeto puede pertenecer o no a un conjunto, pero no puede estar dos veces.

Implementa operaciones matemáticas de conjuntos como intersección, unión y diferencia.

El set es una colección mutable, por lo que se puede agregar o remover elementos. Por su
parte, el frozenset es inmutable, por lo que no se puede modificar, pero puede ser elemento
de otros conjuntos o clave de un diccionario.

- Operaciones.

Python para

Análisis de Datos

Módulo 01

Python para Análisis de Datos


Operaciones

Operadores aritméticos

Existe una variedad de operadores para trabajar con distintos tipos de datos y colecciones. Los
operadores aritméticos (+, -, *, /, //, **, %) son operadores binarios que permiten realizar
operaciones entre números, aunque algunos también funcionan para colecciones, como + y *.
También existe el operador @ para multiplicación matricial (funciona con arrays de Numpy).

Estos operadores tienen un orden de precedencia: ** se calcula antes que *, /, //, % y estos
antes que + y -. Para alterar el orden de estas operaciones en una expresión se utilizan
paréntesis.

Operadores de comparación

Hay tres categorías de comparación: por valor, pertenencia e identidad y todos devuelven
siempre booleanos. Los operadores de comparación por valor son ==, !=, >, >=, <, <= que
comparan los valores respectivos de los operandos, que no necesitan ser del mismo tipo de
dato.

En general, los operadores de igualdad == y != están implementados para todos los tipos de
datos mientras que los operadores de orden sólo están implementados para algunos tipos,
como los numéricos y los strings. Los operadores aritméticos tienen precedencia por sobre los
de comparación.

El operador === comprueba si dos operandos son iguales por tipo de datos y valor.

Operadores de pertenencia

Devuelven True o False.

Para chequear pertenencia tenemos los operadores in y not in. Para contenedores como listas,
tuplas, sets y frozensets el operador in da True si el objeto es un elemento del contenedor.

Para strings el operador in da True si el primer string es un substring del segundo, por lo que es
más amplio que sólo chequear pertenencia de caracteres.

Para diccionarios se chequea si el objeto es una clave del diccionario, sin importar el valor
correspondiente.

Identidad

Los operadores de identidad is e is not permiten evaluar si los operandos son el mismo objeto
en la memoria, lo que internamente se determina usando la función id().

Esto es útil para saber si dos variables apuntan al mismo objeto en la memoria o no, ya que el
operador == solo compara si los operandos, que pueden ser objetos distintos, tienen el mismo
valor o no.
Operadores lógicos

Por último, tenemos los operadores lógicos, aquellos que operan sobre booleanos y devuelven
un booleano. Se trata de los operadores de conjunción, disyunción y negación, cuyos
operadores son and, or y not.

Estos operadores tienen el menor nivel de precedencia, por lo que se evalúan últimos en una
expresión. Los resultados de estos operadores están dados por las tablas de verdad.

Funciones incorporadas

Python tiene una variedad de funciones incorporadas para realizar distintos tipos de tareas sin
la necesidad de importarlas.

Algunas son para construir y convertir entre distintos tipos de datos (como int(), float(),
complex(), bool(), str(), list(), tuple(), dict(), set(), frozenset()), para trabajar con números
(round(), abs(), divmod()), colecciones (len(), min(), max(), sorted(), reversed(), map(), filter()) y
con el bucle for (range(), enumerate(), zip()). Esto le da gran flexibilidad al lenguaje.

Para consultar la documentación de una función cualquiera desde Jupyter Notebook solo hay
que colocar el cursor al lado del nombre de la función y apretar Shift + Tab. Para crear una
nueva línea, letra B. Para cambiar de modo edición a modo visualización, letra M.

Métodos

También se dispone de métodos para realizar acciones sobre tipos de dato en particular. Por
ejemplo, para listas tenemos los métodos append, insert, copy, pop, extend, etc. Distintos
tipos de datos implementan distintos métodos, extendiendo las funcionalidades del lenguaje.

Para ver los métodos disponibles para un objeto en Jupyter Notebook solo hay que tipear el
nombre de la variable que referencia al objeto seguido de un punto y luego apretar Tab. Se
muestra una lista con los métodos disponibles.

Acceder a la documentación de los métodos es igual que con las funciones.

4. Estructuras

- Estructuras de control.
Las estructuras de control permiten controlar el flujo de ejecución de un programa, que de
otro modo es de arriba hacia abajo. Las más básicas son el condicional y los bucles, aunque
funciones y clases también son estructuras de control.

Las instrucciones que pertenecen al bloque de código de la estructura se indica con sangría.
Estas estructuras se pueden combinar de diversas maneras y anidar unas dentro de otras para
obtener el resultado deseado.

Condicional

Permite decidir si se ejecuta un bloque de código o no en base a una condición. Se utilizan las
palabrasif, elif y else en distintas combinaciones. En Python no existe la estructura switch/case,
pero se puede recrear con if/elif.

Bucle while

El bucle while es un bucle condicional que ejecuta un bloque de código siempre que la
condición se evalúe a True. Remarquemos que la condición puede ser cualquier expresión,
cuyo resultado se va a convertir a booleano. En general, todo tipo de dato tiene un único valor
que se evalúa a False mientras todos los demás se evalúan a True.

Para números ese valor es cero. Para colecciones ese valor es la colección vacía.

Bucle for

El bucle for permite iterar sobre cada uno de los elementos de un iterable, como una lista, por
ejemplo. El bucle recorre cada elemento y lo asigna a una variable definida en el propio bucle.
Así, podemos hacer uso del elemento refiriéndonos a la variable.

Resulta ser un iterable todo objeto que implemente el protocolo de iteradores de Python a
través de los métodos __iter__ y __next__. Por ejemplo, además de usar el bucle for con las
colecciones de Python, lo podemos hacer también con archivos, cursores de bases de datos,
arrays de Numpy, series y dataframes de Pandas, etc.
Cuando se itera sobre una secuencia, se recorre cada uno de sus elementos. Sin embargo,
cuando se itera sobre un diccionario se recorre cada una de las claves.

Ejemplo: Diccionario de frecuencias. Supongamos que tenemos una lista con varios elementos
y queremos saber cuántas veces aparece cada uno. Podemos usar un diccionario para llevar
este registro mientras recorremos la lista.

Comenzamos con un diccionario vacío y recorremos la lista con un bucle for. Cada vez que nos
encontremos con un elemento que no está en la lista tenemos que iniciar la correspondiente
entrada con una cuenta de 1. Si el elemento ya está en el diccionario hay que sumar 1 a la
respectiva cuenta.

Listas por comprensión

Existe una sintaxis que permite crear listas de una forma muy concisa: listas por comprensión.
Consiste en especificar los elementos que va a contener la lista en la propia definición de la
lista. Consiste en colocar dentro de los corchetes una expresión y una cláusula for (que puede
o no estar seguida de más cláusulas for o un if). Se usa para generar elementos que siguen un
patrón o aplicar transformaciones a los elementos de otra secuencia.
La función range() devuelve una secuencia de números, comenzando desde 0 de forma
predeterminada, se incrementa en 1 (de forma predeterminada) y se detiene antes de un
número especificado. En este caso es una secuencia de números que van del 0 al 9.

5. Prácticas

- Laboratorio.

Para poder realizar el Laboratorio se recomienda:

* Leer contenidos previos.

* Descarga el material necesario de la carpeta Descargas.

* Se puede trabajar desde el editor de Google https://colab.research.google.com/

Un archivo IPYNB (significa IPython Notebook, porque así se llamaba antes Jupyter Notebook)
es un documento de cuaderno utilizado por Jupyter Notebook, un entorno computacional
interactivo diseñado para ayudar a los científicos a trabajar con el lenguaje Python y sus datos.
Incluye las entradas y salidas de cálculos, matemáticas, aprendizaje automático, imágenes y
más.

Ejercicio 1

Dada una lista de números encontrar el promedio de sus elementos:

1. Sin usar ninguna función.

numeros = [6,3,2,5,4,8,4,5,9,6,8,5,1,5]

suma = 0
n = 0
for num in numeros:
suma += num
n += 1
suma/n
Resultado: 5.071428571428571

2. Usando funciones incorporadas de Python.

sum(numeros)/len(numeros)

Resultado: 5.071428571428571

Ejercicio 2

Dadas dos listas encontrar todos los elementos que tienen en común:

1. Usando bucles.

lista1 = [0,1,2,3,4,5,6,4,5,6,4,4,6]

lista2 = [4,5,6,6,6,7,8,9]

elementos_comunes = []

for item in lista1:

if item in lista2 and item not in elementos_comunes:

elementos_comunes.append(item)

elementos_comunes

Resultado: [4, 5, 6]

2. Usando conjuntos.

elementos_comunes = set(lista1).intersection(set(lista2))

elementos_comunes

Resultado: {4, 5, 6}
Ejercicio 3

Dadas dos listas, contar cuántas veces aparece en una de ellas los elementos que tienen en
común. Es decir, el subconjunto intersección, con la frecuencia de ocurrencias.

lista1 = [0,1,2,3,4,5,6,4,5,6,4,4,6]

lista2 = [4,5,6,6,6,7,8,9]

frecuencias = {}

for item in lista1:

if item in lista2:

if item in frecuencias:

frecuencias[item] += 1

else:

frecuencias[item] = 1

frecuencias

Resultado: {4: 4, 5: 2, 6: 3}

Ejercicio 4

Crear una lista con los primeros 10 múltiplos de 5:

1. Usando bucles tradicionales.

multiplos = []

for i in range(10):

multiplos.append(5 * i)

multiplos

Resultado: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]

2. Usando listas por comprensión.

multiplos = [5*i for i in range(10)]

multiplos

Resultado: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
Ejercicio 5

Dadas dos listas, crear otra que tenga los elementos que están en la primera y que no están en
la segunda:

1. Usando bucles tradicionales.

lista1 = [0,1,2,3,2,3,1,5,4,5,4,6,3,5]

lista2 = [4,5,6,7,8,9]

resta = []

for item in lista1:

if item not in lista2:

resta.append(item)

resta
Resultado: [0, 1, 2, 3, 2, 3, 1, 3]

2. Usando listas por comprensión.

resta = [item for item in lista1 if item not in lista2]

resta
Resultado: [0, 1, 2, 3, 2, 3, 1, 3]

Cada elemento debe aparecer tantas veces como en la lista original.

Ejercicio 6

Dada una lista de números encontrar el promedio de los que sean pares:

1. Usando solamente estructuras de control. (La lista del ejemplo tiene 220.000 elementos)

numeros = [5,4,2,6,9,5,9,10,0,2,8,0,7,1,6,0,3,8,1,0,6,7] * 10000

suma = 0

n=0

for num in numeros:

if num%2==0:

suma += num

n += 1

suma/n
Resultado: 4.0
2. Usando listas por comprensión y funciones incorporadas.

numeros = [5,4,2,6,9,5,9,10,0,2,8,0,7,1,6,0,3,8,1,0,6,7] * 10000

pares = [num for num in numeros if num%2==0]

sum(pares)/len(pares)
Resultado: 4.0
- Laboratorio resuelto.

También podría gustarte