import pandas as pd
#Este comando lo que hace básicamente es decir que quiere accedeer a todas las clases
#que la librería pandas tiene
import numpy as np

"""
Explanation: Introducción a pandas, una librería para analizar datos
A petición de la comunidad, vamos a empezar a ver cómo podemos usar herramientas para analizar datos!!!
Pandas es una librería muy usada en "data science" ya que te permite cargar y operar rápidamente en python. En lo que se enfoca es en procesar arreglos de datos que tengan la forma n x m en donde "n" sean el número de filas (rows) y "m" el número de columnas. Cada columna puede contener más de un tipo de datos (no es como en numpy que todo tiene que ser lo mismo).
Ahora sin más preámbulos empecemos a usar pandas!!
Lo primero que hay que hacer es importar la librería. Para ello necesitamos que esté instalada. Todas las personas que tienen anaconda no deben de preocuparse por instalar ninguna otra cosa. El resto debe de hacerlo de acuerdo a como instaló python en un principio.
End of explanation
"""


lista = ['hola', 'mi', 'nombre', 'es', 'pandas',0.18 ]
serie = pd.Series(lista)
print(lista)
print(serie)

"""
Explanation: Ahora que ya tenemos pandas podemos empezar a explorar que cosas podemos hacer con esta librería.
En pandas hay dos tipos nuevos de estructura de datos. Pregunta rápida, recuerdas los otros tipos de datos que hemos visto??
De regreso al punto :P los nuevos tipos de datos se separan en dos grupos: las series y los "data frames".
Las series son el elemento más simple en pandas ya que es una arreglo de n x 1 es decir n número de filas con una sola columna. Veamos un ejemplo:
End of explanation
"""


serie2 = pd.Series(lista, index=['H', 'm', 'n', 'e', 'p', '0'])
serie2

"""
Explanation: Pregunta 1
¿Qué diferencias notas entre la lista y la serie?
Ajá!! Exactemente!! esos pequeños numerillos a la izquierda, ¿Qué te imaginas que son?
Pues esos pequeños se llaman índices y son un concepto muy útil que hay que entender porque pandas se maneja principalmente con índices. Ahora veamos como podemos nombrar como queramos a esos índices.
End of explanation
"""


diccionario = {'Ciudad de México':'Tacos al pastor', 'Puebla':'Chile en nogada', 'Yucatán':'Cochinita'}

serie_dic = pd.Series(diccionario)
serie_dic

serie_dic.loc['Puebla':'Yucatán']

lista2 = [1,1,1,1,1,1]

"""
Explanation: Te recuerda esto a alguna estructura de datos que ya hemos visto?
ejem, ejem, dic..., ejem, ejem...
Pues si se podría pensar en una serie como una especie de diccionarios, de hecho para crear una serie también puedes partir de un diccionario...
End of explanation
"""


ejemplo=pd.Series(lista, lista2)

ejemplo[1]

"""
Explanation: Pregunta 2
¿Qué crees que pase si queremos hacer una serie con la lista 1 pero que tenga como índices la lista 2?
End of explanation
"""


#Crear un data frame de un arreglo de numpy
arreglo = np.random.randn(7,3)
print(arreglo)
columnas = list('ABC')
data_frame = pd.DataFrame(arreglo, columns=columnas )

data_frame

"""
Explanation: Como pudiste darte cuenta, en realidad las series sí se parecen a los diccionarios pero no son exactamente lo mismo... Si quieres saber de qué otras maneras puedes crear series, puedes visitar la página de documentación oficial, está super completa!!
Ahora que ya conoces la materia prima de pandas podemos empezar a trabajar con data frames que si lo piensas, serían como un montón de series amarradas entre sí...
Para crear un data frame hay varias formas, puedes escribirlo todo de la misma forma que hicimos con las series pero también puedes importar una set de datos con el que quieras trabajar.
Veremos rápidamente como podemos crear un data frame y luego como podemos cargar uno que ya tengamos.
End of explanation
"""


df_diccionario = pd.DataFrame({'A':list(range(5)),
                              'B': np.random.random_sample(5),
                              'C':'Jueves'})

df_diccionario

"""
Explanation: Si quieres saber mas detalles de lo que la función random.randn de numpy hace, puedes checar esta página
Así de simple se puede generar un data frame, pero también podemos hacerlo con diccionarios...
End of explanation
"""


mi_df = pd.read_csv('FreeFattyAcids.csv', header=0)
mi_df

"""
Explanation: Así de simple es crear un data frame. Ahora veamos lo que todos estaban esperando!! Crear data frames a partir de datos que esten en hojas de excel o en csv o txt. Que justamente son los que se generan en los experimentos que algunas de ustedes lleguen a hacer o que otras personas hagan para que ustedes los analicen.
Vamos a ver un ejemplo con un set de datos pequeño.
End of explanation
"""


mi_df.head()

#Por default nos va a mostras las primeras 5 filas después del encabezado,
#pero podemos cambiarlo pasando un argumento a head()
mi_df.head(3)

#Para ver la "cola"
mi_df.tail(3)

"""
Explanation: Este set de datos es de un perfil lipídico obtenido con espectrometría de masas. Son tres condiciones, una control y dos tratamientos, para cada una de ellas se puede ver la concentración de ácidos grasos de cadenas de 12 hasta 26 carbonos. 
Por suerte este data frame es pequeño y podemos visualizar casi todo, pero imaginemos que tenemos 1000000 de columnas, en realidad no necesitamos verlo todo, pero queremos saber más o menos como está organizado nuestro data frame. Para esto podemos acceder a un método de mi_df para ver nada más la "cabeza" (o la "cola") de nuestros datos.
End of explanation
"""


mi_df[0:5]

"""
Explanation: Pero una vez que tenemos los datos ¿qué hacemos con ellos? Pues bien en realidad eso depende mucho de las preguntas que queramos responder empecemos con unas preguntas fáciles.
Pregunta 3
Digamos que a mí sólo me interesa saber cómo cambia el total, ¿Cómo puedo hacer que en un data frame sólo me muestre la columna "Sample" y la columna "Total"?
Para responder esta cuestión, necesitamos saber como hacer "slicing" de los data frames, esto es, sacar subgrupos de un data frame para analizarlo más fácilmente. Alguien tiene alguna idea que podamos probar??
End of explanation
"""


mi_df["Sample"]

#o algo padre que también es posible en pandas es acceder a columnas con puntos
mi_df.Sample

"""
Explanation: En pandas una de las cosas más confusas (especialmente si tienes tiempo trabajando con numpy) es sacar subgrupos de datos. La forma en la que pandas está diseñado para esto es a través de índices y encabezados.
End of explanation
"""


mi_df[["Sample","16:0"]][0:4].plot()

import matplotlib.pyplot as plt

plt.show()

mi_df[0:3]

"""
Explanation: Pero si queremos seleccionar múltiples columnas separadas podemos hacer lo siguiente
End of explanation
"""


mi_df.loc[0:4,'Sample']

#¿qué pasa si sólo pongo el nombre de la columna?
mi_df.loc['Sample']

mi_df.loc[:, 'Sample']

mi_df.loc[mi_df['14:0']>100]#Esto es un slicing dado un arreglo booleano

mi_df['14:0']>100

"""
Explanation: Selección por índice
Para seleccionas sólo por índice tenemos que agregar la terminación .loc después del nombre de nuestro data frame y luego poner los índices que queramos con los nombres de las columnas que nos interesen.
Esta sección es de la documentación de pandas y dice lo siguiente acerca del atributo .loc.

Este atributos es el método primario de acceso (a los datos). Los siguientes son inputs válidos:
1. Una etiqueta (que es estrictamente de los índices)
2. Una lista o arreglo de etiquetas
3. Un slice de etiquetas (nota, al contrario de lo que se hace en python, el número inicial y final están incluídos!)
4. Un arreglo booleano
5. Un "callable"
End of explanation
"""


mi_df.iloc[0:3, -1]

mi_df.Total.mean()

"""
Explanation: Selección por posición.
Es la más parecida a como opera numpy, y aquí sólo tienes que darle las posiciones que quieres (en números) de filas y columnas. Para esto usamos el atributo .iloc después de nuestro data frame.
Aquí los argumentos válidos son los siguientes:

integer e.g. 5
Lista o arreglo de enteros [4, 3, 0]
Un objeto slice con ints 1:7
Un arreglo booleano
Un "callable"
End of explanation
"""


mi_df[['Sample','Total']]

"""
Explanation: Ahora si hagamos unos ejercicios pa' que amarre
Ejercicio 1
Has un df que tenga sólo las columnas Sample y Total
End of explanation
"""


serie=mi_df.loc[:,'18:0']

print (serie.idxmax())
print (serie.max())

mi_df.loc[5,'Sample']

"""
Explanation: Ejercicio 2
Muestrame que Sample tiene el mayor número de ácidos grasos de cadena 18:0
End of explanation
"""


mi_df.Total.sort

"""
Explanation: Ejercicio 3
Cuáles son los tres samples con mayor número de ácidos grasos libres totales
End of explanation
"""


