<jupyter_start><jupyter_text>![](./imagenes/python_logo.jpeg) Librería Pandas.*** [*Pandas*](https://pandas.pydata.org/pandas-docs/stable/) es sin duda el paquete más importante de *Python* utilizado en la *Ciencia de Datos*. No solo ofrece muchos métodos y funciones que facilitan el trabajo con los datos, sino que además se ha optimizado para la velocidad, lo que le brinda una ventaja significativa en comparación al trabajo con datos numéricos en *Python*.*Pandas* es una librería que provee estructuras de datos rápidas, flexibles y expresivas; diseñadas para trabajar con *rotulados* y/o *relacionales*. Conceptualmente se puede pensar como *arrays* de *NumPy* donde las filas y columnas están *rótuladas*. Las estructuras de datos de *Pandas* tienen forma similar a hojas de cálculo en *Python*.Asi como *NumPy*, *Pandas* es una muy buena herramienta para trabajar con números, vectores, álgebra lineal, etc. *Pandas* es adecuado para trabajar con:* Datos tabulares y heterogéneos (flotantes, string, enteros, etc.)* Series temporales.* Los mismos datos que se pueden manipular con arreglos de *NumPy*.*Pandas* no forma parte de la instalación estándar de *Python*, así que debe instalarse por separado. Para instalar *Pandas* debe ejecutarse el siguiente comando desde una cónsola o terminal:```bashpip install pandas```Además, para trabajar con archivos de Excel, también deberá ejecutarse:```bashpip install xlrd```La siguiente *hoja-resumen* condensa los principales comandos de *Pandas* que revisaremos en este *Notebook* y que luego podrá servir para consulta rápida.![](./imagenes/cheat_sheet_pandas.png)*Pandas* tiene una documentación muy completa y diversos [tutoriales](http://pandas.pydata.org/pandas-docs/stable/tutorials.html).En *Pandas* existen tres tipos básicos de objetos todos ellos basados a su vez en *NumPy*:* *Series* (listas, 1D),* *DataFrame* (tablas, 2D) y* *Panels* (tablas 3D).Nosotros vamos a ver el uso básico de los dos primeros tipos de objetos, para un mayor detalle puedes consultar el [manual](http://pandas.pydata.org/pandas-docs/stable/dsintro.html).En este notebook vamos a usar la abreviación:* **df**: para cualquier objeto `DataFrame` *Pandas*.* **s**: para cualquier objeto de `Series` *Pandas*.Para comenzar iniciamos importando *Pandas* según la convención:<jupyter_code>import pandas as pd<jupyter_output><empty_output><jupyter_text>Importador de datos.<jupyter_code>csv_data  = "datos/capacitaciones.csv"
json_data = "datos/capacitaciones.json"
xlsx_data = "datos/capacitaciones.xlsx"

df = pd.read_csv(csv_data, encoding = "ISO-8859-1") # De un archivo CSV.
df = pd.read_json(json_data)                        # De un archivo JSON.
df = pd.read_excel(xlsx_data)                       # De un archivo XLSX.<jupyter_output><empty_output><jupyter_text>Existen otros tipos de *importadores* de datos, tales como:* `pd.read_table(filename)`: importa desde un archivo de texto delimitado (como TSV).* `pd.read_sql(query, connection_object)`: importa desde una BaseDeDatos/Tabla SQL.* `pd.read_html(url)`: importa desde una URL html, una cadena o un archivo y extrae tablas a una lista.* `pd.read_clipboard()`: toma los datos desde el contenido del portapapeles.* `pd.DataFrame(dict)`: importa desde un diccionario *Python*.  Exportador de datos. Los *exportadores* de datos guardan en disco los datos del *df*:* `df.to_csv(filename)`: escribe los datos en un archivo CSV.* `df.to_excel(filename)`: escribe los datos en un archivo Excel.* `df.to_sql(table_name, connection_object)`: escribe los datos en una tabla SQL.* `df.to_json(filename)`: escribe los datos en un archivo con formato JSON;  Crear objetos de prueba. Crear datos de prueba es útil para probar segmentos de código:<jupyter_code># Genera un dataframe con 5 columnas y 10 filas.
df = pd.DataFrame(pd.np.random.rand(10, 5))
df
# Crea una series a partir de una lista.
my_list = [2, 7, 3, 9, 5]
s = pd.Series(my_list)
s
# Añade un índice de fecha al dataframe.
df.index = pd.date_range('1900/1/30', periods = df.shape[0])
df<jupyter_output><empty_output><jupyter_text>Visualizar / inspeccionar datos.<jupyter_code>df.head(5) # Muestra las primeras 5 filas del DataFrame.
df.tail(5) # Muestra las últimas 5 filas del DataFrame.
df.shape # Muestra el número de filas y columnas del DataFrame.
df.info() # Muestra el índice, tipo de datos y memoria.
df.describe() # Muestra estadísticas resumidas de columnas numéricas.
s.value_counts(dropna = False) # Muestra valores y recuentos únicos en la serie.<jupyter_output><empty_output><jupyter_text>Selección.<jupyter_code>df[2] # Devuelve la columna con la etiqueta 2 como una Series.
df[[2, 4]] # Devuelve columnas 2 y 4 como un nuevo DataFrame.
s.iloc[0] # Selección por posición: selecciona el elemento 0 de la Series.
s.loc[3] # Selección por índice de la Series.
df.iloc[0, :] # Primera fila del DataFrame.
df.iloc[0, 0] # Primer elemento de la primera columna.<jupyter_output><empty_output><jupyter_text>Limpieza de datos.<jupyter_code>df.columns = ["a", "b", "c", "x", "y"] # Renombrar columnas del DataFrame.
df
df.isnull() # Comprueba valores nulos, devuelve un Boolean Arrays.
df.notnull() # El opuesto a df.isnull().
df.dropna(axis = 0) # Elimina todas las filas que contienen valores nulos.
df.dropna(axis = 1) # Elimina todas las columnas que contienen valores nulos
# Elimina todas las filas que tienen menos de 3 valores no nulos.
df.dropna(axis = 1, thresh = 3)
df.fillna(0) # Remplaza todos los valores nulos por 0.
s.fillna(s.mean()) # Remplaza todos los valores nulos por la media.
s.astype(float) # Convierte el tipo de datos a float.
s.replace(3, '100') # Remplaza todos los valores iguales a 3 con '100'.
s.replace([7, 9], ['700', '900']) # Remplaza todos los 7 por '700' y 9 por '900'.
df.columns = (0, 1, 2, 3, 4)
df.rename(columns = lambda x: 2*x + 1) # Cambio de nombre de columnas en masa.
df.rename(columns={1:'one'}) # Renombrar seleccionando columna.
df.set_index(2) # Cambiar el índice por una columna (2) del Dataframe.
df.set_index(2).rename(index = lambda x: x + 1) # Cambia el índice en lote.<jupyter_output><empty_output><jupyter_text>Filtro, orden y agrupamiento.<jupyter_code>df[df[2] > 0.5] # Filtra las filas donde la columna 2 es mayor que 0.5
df[(df[2] > 0.5) & (df[2] < 0.7)] # Filtra las filas donde 0.7 > columna 2 > 0.5
df.sort_values(3) # Ordena por los valores de la columna 3 en orden ascendente.
df.sort_values(3, ascending = False) # Ordena por la columna 3 en orden descendente.
# Ordena los valores por la columna 2 de forma ascendente
# y luego por la columna 3 en orden descendente.
df.sort_values([2, 3], ascending = [True, False])
df.groupby(3) # Devuelve un objeto groupby para los valores de una columna.
# Devuelve un objeto groupby para valores de múltiples columnas,
# en este caso columnas 3 y 4.
df.groupby([3, 4])
# Crea una tabla dinámica que agrupa por la columna 2
# y calcula la media de las columnas 3 y 4.
df.pivot_table(index = 2, values = [3, 4], aggfunc = pd.np.mean)
# Encuentra el promedio en todas las columnas
# para cada grupo de la columna 3 único.
df.groupby(3).agg(pd.np.mean)
df.apply(pd.np.mean) # Aplica la función pd.np.mean() en cada columna.
df.apply(pd.np.max, axis = 1) # Aplica la función pd.np.max() en cada fila.<jupyter_output><empty_output><jupyter_text>Unir / Combinar. Para ejemplificar la unión y conbinación de dataframes, supongamos que tenemos los siguientes dos dataframes:<jupyter_code>data_1 = {"A": [1, 2, 3, 4],
          "B": ["a", "b", "c", "d"],
          "C": ["w", "x", "y", "z"]}
df1 = pd.DataFrame(data_1)
df1
data_2 = {"A": [6, 7, 3, 4],
          "B": [True, False, True, False],
          "C": [1, 2, 3, 4]}
df2 = pd.DataFrame(data_2)
df2
# Agrupa las filas en df1 al final de df2 (las columnas deben ser idénticas).
df1.append(df2)
# Agrega las columnas en df1 al final de df2 (las filas deben ser idénticas)
pd.concat([df1, df2], axis = 1)
# Une las columnas en df1 con las columnas en df2 donde las filas para A
# tienen valores idénticos. También puede utilizarse: left, right, outer, inner.
pd.merge(df1, df2, on = ["A"], how = 'inner')<jupyter_output><empty_output><jupyter_text>Estadísticas.<jupyter_code>df.describe() # Resumen de estadísticas para columnas numéricas.
df.mean(axis = 0) # Devuelve la media de todas las columnas.
df.mean(axis = 1) # Devuelve la media de todas las filas.
df.corr() # Devuelve la correlación entre las columnas en un DataFrame.
df.count(axis = 0) # Devuelve el número de valores no nulos en cada columna.
df.max(axis = 0) # Devuelve el valor más alto en cada columna.
df.min(axis = 0) # Devuelve el valor más bajo en cada columna
df.median(axis = 0) # Devuelve la mediana de cada columna.
df.std(axis = 0) # Devuelve la desviación estándar de cada columna.<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1104796544669243, 'fraction_numerical': 0.01875426233234826, 'mean_word_length': 4.732247557003257, 'pattern_counts': {'":': 6, '<': 38, '<?xml version=': 0, '>': 41, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '623032', 'license': 'MIT', 'n_tokens_mistral': 3337, 'n_tokens_neox': 3229, 'n_words': 1108, 'path': '04_pandas.ipynb', 'repo_name': 'ejdecena/herramientas', 'size': '8798'}