Operaciones¶
Operaciones Básicas¶
Pandas es una biblioteca de Python para la manipulación y análisis de datos. Aquí están algunas de las operaciones básicas de Pandas que puedes realizar en un DataFrame:
pd.read_csv()
: para leer archivos CSV y crear un DataFrame.df.to_csv('filename.csv')
: para guardar el DataFrame en un archivo CSV.df.head(n)
: para mostrar los primeros n elementos del DataFrame.df.tail(n)
: para mostrar los últimos n elementos del DataFrame.df.info()
: para obtener información sobre el DataFrame, como el tipo de datos, el número de valores no nulos, etc.df.describe()
: para obtener estadísticas descriptivas del DataFrame, como la media, la mediana, el valor mínimo y máximo, etc.df.shape
: para obtener el número de filas y columnas del DataFrame.df.dtypes
: para obtener los tipos de datos de cada columna del DataFrame.df.unique()
: para obtener valores únicos en una columna del DataFrame.df.nunique()
: para obtener el número de valores únicos en cada columna del DataFrame.df.value_counts()
: para obtener el número de ocurrencias de cada valor en una columna del DataFrame.df.sort_values(column_name)
: para ordenar el DataFrame por valores en una columna.df.rename(columns={'old_name': 'new_name'})
: para cambiar los nombres de las columnas en el DataFrame.df.apply(func)
: para aplicar una función a cada columna o fila del DataFrame.
Veamos un ejemplo aplicado:
import pandas as pd
import numpy as np
data = {
'nombre': [f'N{x}' for x in range(1,10+1) ],
'valor': [1,1,2,2,2,3,3,4,4,5]
}
df = pd.DataFrame(data)
df
nombre | valor | |
---|---|---|
0 | N1 | 1 |
1 | N2 | 1 |
2 | N3 | 2 |
3 | N4 | 2 |
4 | N5 | 2 |
5 | N6 | 3 |
6 | N7 | 3 |
7 | N8 | 4 |
8 | N9 | 4 |
9 | N10 | 5 |
# priemras filas
df.head()
nombre | valor | |
---|---|---|
0 | N1 | 1 |
1 | N2 | 1 |
2 | N3 | 2 |
3 | N4 | 2 |
4 | N5 | 2 |
# ultimas filas
df.tail()
nombre | valor | |
---|---|---|
5 | N6 | 3 |
6 | N7 | 3 |
7 | N8 | 4 |
8 | N9 | 4 |
9 | N10 | 5 |
# informacion del dataframe
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 10 entries, 0 to 9 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 nombre 10 non-null object 1 valor 10 non-null int64 dtypes: int64(1), object(1) memory usage: 288.0+ bytes
# estadisticas basicas
df.describe()
valor | |
---|---|
count | 10.000000 |
mean | 2.700000 |
std | 1.337494 |
min | 1.000000 |
25% | 2.000000 |
50% | 2.500000 |
75% | 3.750000 |
max | 5.000000 |
# filas y columnas
df.shape
(10, 2)
# tipo de datos por columnas
df.dtypes
nombre object valor int64 dtype: object
# objetos unicos por columna especifica
df['valor'].unique()
array([1, 2, 3, 4, 5], dtype=int64)
# cantidad de objetos unicos - todas las columnas
df.nunique()
nombre 10 valor 5 dtype: int64
# cantidad de objetos unicos - columna especifica
df['valor'].nunique()
5
# numero de ocurrencias de cada valor en una columna
df['valor'].value_counts()
valor 2 3 1 2 3 2 4 2 5 1 Name: count, dtype: int64
# ordenar valores - por columna especifica, menor a mayor
df.sort_values('valor', ascending = True)
nombre | valor | |
---|---|---|
0 | N1 | 1 |
1 | N2 | 1 |
2 | N3 | 2 |
3 | N4 | 2 |
4 | N5 | 2 |
5 | N6 | 3 |
6 | N7 | 3 |
7 | N8 | 4 |
8 | N9 | 4 |
9 | N10 | 5 |
# ordenar valores - por columna especifica, mayor a menor
df.sort_values('valor', ascending = False)
nombre | valor | |
---|---|---|
9 | N10 | 5 |
7 | N8 | 4 |
8 | N9 | 4 |
5 | N6 | 3 |
6 | N7 | 3 |
2 | N3 | 2 |
3 | N4 | 2 |
4 | N5 | 2 |
0 | N1 | 1 |
1 | N2 | 1 |
# cambiar nombre de columnas
df.rename(columns={
'nombre': 'Nombre',
'valor':'Valor'
})
Nombre | Valor | |
---|---|---|
0 | N1 | 1 |
1 | N2 | 1 |
2 | N3 | 2 |
3 | N4 | 2 |
4 | N5 | 2 |
5 | N6 | 3 |
6 | N7 | 3 |
7 | N8 | 4 |
8 | N9 | 4 |
9 | N10 | 5 |
# aplicar funcion columna especifica
df['valor']
0 1 1 1 2 2 3 2 4 2 5 3 6 3 7 4 8 4 9 5 Name: valor, dtype: int64
# funcion apply
df['valor'] = df['valor'].apply(np.sqrt)
df
nombre | valor | |
---|---|---|
0 | N1 | 1.000000 |
1 | N2 | 1.000000 |
2 | N3 | 1.414214 |
3 | N4 | 1.414214 |
4 | N5 | 1.414214 |
5 | N6 | 1.732051 |
6 | N7 | 1.732051 |
7 | N8 | 2.000000 |
8 | N9 | 2.000000 |
9 | N10 | 2.236068 |
Operaciones Matemáticas¶
Al igual que numpy, las series de pandas pueden realizar operaciones matemáticas similares (mientrás los arreglos a operar sean del tipo numérico).
Podemos realizar operaciones aritméticas en las series, como la suma, resta, la multiplicación y la división, utilizando los operadores +
,-
, *
y /
, respectivamente.
s1 = pd.Series([1,2,3,4,5])
s2 = pd.Series([1,1,2,2,2])
# suma
print(f"suma: \n{s1+s2}\n")
# resta
print(f"resta: \n{s1-s2}\n")
# multiplicacion
print(f"multiplicacion: \n{s1*s2}\n")
# division
print(f"division: \n{s1/s2}")
suma: 0 2 1 3 2 5 3 6 4 7 dtype: int64 resta: 0 0 1 1 2 1 3 2 4 3 dtype: int64 multiplicacion: 0 1 1 2 2 6 3 8 4 10 dtype: int64 division: 0 1.0 1 2.0 2 1.5 3 2.0 4 2.5 dtype: float64
Además, Pandas también proporciona una serie de funciones útiles para realizar operaciones estadísticas en las series, como mean()
, std()
, min()
, max()
y otras. Estas funciones se pueden utilizar para calcular estadísticas de resumen de una serie.
# operaciones estadisticas
s1 = pd.Series([1,1,1,2,2,2,3,3,3,4,5,5,5,5])
print(f"mean: {s1.mean()}") # mean
print(f"std: {s1.std()}") # std
print(f"min: {s1.min()}") # min
print(f"max: {s1.max()}") # max
mean: 3.0 std: 1.5689290811054724 min: 1 max: 5
También, se pueden realizar una variedad de operaciones matemáticas en un DataFrame. Al igual que con las series, las operaciones se realizan elemento por elemento. Aquí hay algunos ejemplos de operaciones matemáticas comunes en un DataFrame.
# Crear un DataFrame
df = pd.DataFrame({
'A': [2, 1, 3],
'B': [1, 2, 6],
'C': [3, 10, 9]}
)
df
A | B | C | |
---|---|---|---|
0 | 2 | 1 | 3 |
1 | 1 | 2 | 10 |
2 | 3 | 6 | 9 |
# sumar la columna A de la columna B - opcion dataframe
df['B'].add(df['A'])
0 3 1 3 2 9 dtype: int64
# sumar la columna A de la columna B - opcion series
df['B'] + (df['A'])
0 3 1 3 2 9 dtype: int64
Nota: Lo anterior se extiende para las operaciones restar, multiplicar y dividir.
# Sumar las columnas
column_sum = df.sum(axis=0)
print(column_sum)
A 6 B 9 C 22 dtype: int64
# Sumar las filas
row_sum = df.sum(axis=1)
print(row_sum)
0 6 1 13 2 18 dtype: int64
# resumen estadistico
df.describe()
A | B | C | |
---|---|---|---|
count | 3.0 | 3.000000 | 3.000000 |
mean | 2.0 | 3.000000 | 7.333333 |
std | 1.0 | 2.645751 | 3.785939 |
min | 1.0 | 1.000000 | 3.000000 |
25% | 1.5 | 1.500000 | 6.000000 |
50% | 2.0 | 2.000000 | 9.000000 |
75% | 2.5 | 4.000000 | 9.500000 |
max | 3.0 | 6.000000 | 10.000000 |
# correlaciones lineales
df.corr()
A | B | C | |
---|---|---|---|
A | 1.000000 | 0.755929 | -0.132068 |
B | 0.755929 | 1.000000 | 0.549086 |
C | -0.132068 | 0.549086 | 1.000000 |
Observación
axis
es un parámetro que se utiliza en varias funciones de Pandas para especificar si una operación se realiza a lo largo de las filas (axis=0
) o a lo largo de las columnas (axis=1
) de un DataFrame.
axis=0
se refiere a las filas. Algunas operaciones que se realizan a lo largo del eje 0 son la suma (sum()), el conteo (count()
), la media (mean()
), entre otras.axis=1
se refiere a las columnas. Algunas operaciones que se realizan a lo largo del eje 1 son la transposición (T
), el acceso a una columna (['columna']
), entre otras.
Por ejemplo, si se desea calcular la suma de las columnas y filas de un DataFrame df
, se puede utilizar la función sum()
de la siguiente manera:
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]}
)
df
A | B | C | |
---|---|---|---|
0 | 1 | 4 | 7 |
1 | 2 | 5 | 8 |
2 | 3 | 6 | 9 |
# operacion .sum por defecto
df.sum()
A 6 B 15 C 24 dtype: int64
# sumar columnas
suma_columnas = df.sum(axis=0)
suma_columnas
A 6 B 15 C 24 dtype: int64
# sumar filas
suma_filas = df.sum(axis=1)
suma_filas
0 12 1 15 2 18 dtype: int64
Operaciones Avanzadas¶
Para modificar agregar una columan en una dataframe, existen dos maneras:
# Crear un DataFrame
df = pd.DataFrame({
'A': [2, 1, 3],
'B': [1, 2, 6],
'C': [3, 10, 9]}
)
df
A | B | C | |
---|---|---|---|
0 | 2 | 1 | 3 |
1 | 1 | 2 | 10 |
2 | 3 | 6 | 9 |
# opcion 01 - igualando
df['D'] = 1
df
A | B | C | D | |
---|---|---|---|---|
0 | 2 | 1 | 3 | 1 |
1 | 1 | 2 | 10 | 1 |
2 | 3 | 6 | 9 | 1 |
# ocupando 'assign'
df.assign(D=1)
A | B | C | D | |
---|---|---|---|---|
0 | 2 | 1 | 3 | 1 |
1 | 1 | 2 | 10 | 1 |
2 | 3 | 6 | 9 | 1 |
También puede agregar operaciones entre columnas para crear otra nueva:
# nueva columna a partir de otras dos
df['D'] = df['A']+df['B']
df
A | B | C | D | |
---|---|---|---|---|
0 | 2 | 1 | 3 | 3 |
1 | 1 | 2 | 10 | 3 |
2 | 3 | 6 | 9 | 9 |
Si usted necesita aplicar una función a una columna en específico y dicha función tiene varios parámetros, puede utilizar la notación lambda para trabajar. Veamos un ejemplo:
# crear funcion
def funcion_objetivo(x,y):
return x+2*y
# aplicar funcion
df['D'] = df['A'].apply(lambda x: funcion_objetivo(x,5))
df
A | B | C | D | |
---|---|---|---|---|
0 | 2 | 1 | 3 | 12 |
1 | 1 | 2 | 10 | 11 |
2 | 3 | 6 | 9 | 13 |
Ahora si usted necesita aplicar funcion_objetivo
a dos columnas, realizamos la siguiente operación
df['D'] = df.apply(lambda x: funcion_objetivo(x['A'], x['B']), axis=1)
df
A | B | C | D | |
---|---|---|---|---|
0 | 2 | 1 | 3 | 4 |
1 | 1 | 2 | 10 | 5 |
2 | 3 | 6 | 9 | 15 |
Por otro lado, para copiar la información de un objeto de pandas, siempre debe ocupar .copy()
, ya que en caso contrario, estará guardando los dos objetos en la misma asignación de memoria. Veamos un ejemplo:
from IPython.display import display_html
# correcto - solo se modifica nuevo_df
nuevo_df = df.copy()
nuevo_df['A'] = 1
print(f"df")
display_html(df)
print()
print(f"nuevo_df")
display_html(nuevo_df)
df
A | B | C | D | |
---|---|---|---|---|
0 | 2 | 1 | 3 | 4 |
1 | 1 | 2 | 10 | 5 |
2 | 3 | 6 | 9 | 15 |
nuevo_df
A | B | C | D | |
---|---|---|---|---|
0 | 1 | 1 | 3 | 4 |
1 | 1 | 2 | 10 | 5 |
2 | 1 | 6 | 9 | 15 |
# incorrecto - se modifica df y nuevo_df
nuevo_df = df
nuevo_df['A'] = 1
print(f"df")
display_html(df)
print()
print(f"nuevo_df")
display_html(nuevo_df)
df
A | B | C | D | |
---|---|---|---|---|
0 | 1 | 1 | 3 | 4 |
1 | 1 | 2 | 10 | 5 |
2 | 1 | 6 | 9 | 15 |
nuevo_df
A | B | C | D | |
---|---|---|---|---|
0 | 1 | 1 | 3 | 4 |
1 | 1 | 2 | 10 | 5 |
2 | 1 | 6 | 9 | 15 |
Muchas veces, en un Dataframe se necesita realizar operaciones entre la fila actual y la fila anterior, lo cual puede ser complejo si no se utilizan las funciones correctas. A continuación se trabajan algunas de estas funciones:
shift()
: Se utiliza para mover hacia arriba o hacia abajo los valores de una columna o serie de datos.cumsum()
: es una función que se utiliza para calcular la suma acumulativa de valores a lo largo de un eje en un DataFrame o una Serie.pct_change()
: es una función que se utiliza para calcular el cambio porcentual entre los elementos de una serie o columna en un DataFrame.rank()
: es una función que se utiliza para asignar un rango a los elementos de una serie o columna en un DataFrame.
data = {'ventas': [100,200, 200, 300, 400, 500]}
df = pd.DataFrame(data)
df
ventas | |
---|---|
0 | 100 |
1 | 200 |
2 | 200 |
3 | 300 |
4 | 400 |
5 | 500 |
# aplicar funciones
df['shift'] = df['ventas'].shift() # se muestra el valor de la fila anterior (la primera fila en este caso es NaN)
df['cumsum'] = df['ventas'].cumsum() # suma acumulada entre la fila actual y todas las anteriores
df['pct_change'] = df['ventas'].pct_change() # porcentaje de cambio entre la fila actual y la anterior
df['rank'] = df['ventas'].rank() # ranking de los valores (donde 1 es el menor valor)
df
ventas | shift | cumsum | pct_change | rank | |
---|---|---|---|---|---|
0 | 100 | NaN | 100 | NaN | 1.0 |
1 | 200 | 100.0 | 300 | 1.000000 | 2.5 |
2 | 200 | 200.0 | 500 | 0.000000 | 2.5 |
3 | 300 | 200.0 | 800 | 0.500000 | 4.0 |
4 | 400 | 300.0 | 1200 | 0.333333 | 5.0 |
5 | 500 | 400.0 | 1700 | 0.250000 | 6.0 |
Finalmente, una función que merece nuestra atención es explode
. En Pandas, explode()
es una función que se utiliza para descomponer una columna que contiene listas o arrays en varias filas, una por cada elemento de la lista o array. La sintaxis básica de explode()
es la siguiente:
df.explode(column, ignore_index=False)
donde:
column
: es el nombre de la columna que se va a explotar.ignore_index
: indica si se deben reiniciar los índices después de la explosión. El valor por defecto es False.
Veamos un ejemplo sencillo:
import pandas as pd
data = {'id': [1, 2, 3], 'nombres': [['Juan', 'Pedro'], ['María', 'Luisa'], ['Ana', 'Sofía', 'Lucía']]}
df = pd.DataFrame(data)
df
id | nombres | |
---|---|---|
0 | 1 | [Juan, Pedro] |
1 | 2 | [María, Luisa] |
2 | 3 | [Ana, Sofía, Lucía] |
Si queremos descomponer la columna "nombres" en varias filas, una por cada nombre, podemos utilizar la siguiente sintaxis:
df_exploded = df.explode('nombres')
df_exploded
id | nombres | |
---|---|---|
0 | 1 | Juan |
0 | 1 | Pedro |
1 | 2 | María |
1 | 2 | Luisa |
2 | 3 | Ana |
2 | 3 | Sofía |
2 | 3 | Lucía |
En este ejemplo, se ha utilizado la función explode()
para descomponer la columna "nombres" en varias filas, una por cada nombre. Como resultado, se ha creado un nuevo DataFrame llamado "df_exploded" que contiene tres filas por cada fila del DataFrame original. Cada fila contiene un solo nombre y el valor correspondiente de la columna "id" se ha replicado para cada fila.