Manejo de datos con Pandas

Manejo de datos con Pandas Manejo de datos con Pandas

Manejo de datos con Pandaslink image 0

1. Resumenlink image 1

Vamos a ver una pequeña introducción a la librería de manipulación y análisis de datos Pandas. Con ella podremos manejar y procesar datos tabulares que nos ayudará para poder operar con ellos y obtener información de una manera muy valiosa

No description has been provided for this image

2. ¿Qué es Pandas?link image 2

Pandas es una librería de Python que está diseñada para que el trabajo con datos relacionales o etiquetados sea fácil e intuitivo

Pandas está diseñado para muchos tipos diferentes de datos:

  • Datos tabulares con columnas de tipos heterogéneos, como en una tabla SQL o una hoja de cálculo de Excel
  • Datos de series de tiempo ordenados y desordenados (no necesariamente de frecuencia fija).
  • Datos matriciales arbitrarios (homogéneos o heterogéneos) con etiquetas de fila y columna
  • Cualquier otra forma de conjuntos de datos observacionales/estadísticos. No es necesario etiquetar los datos en absoluto para colocarlos en una estructura de datos de pandas.

Las dos estructuras de datos principales de Pandas son las Series (unidimensional) y los DataFrames (bidimensional). Pandas está construido sobre NumPy y está destinado a integrarse bien dentro de un entorno informático científico con muchas otras bibliotecas de terceros. Para los científicos de datos, el trabajo con datos generalmente se divide en varias etapas: recopilar y limpiar datos, analizarlos/modelarlos y luego organizar los resultados del análisis en una forma adecuada para trazarlos o mostrarlos en forma de tabla. pandas es la herramienta ideal para todas estas tareas. Otra característica es que pandas es rápido, muchos de los algoritmos de bajo nivel se han construido en C.

2.1. Pandas como pdlink image 3

Generalmente a la hora de importar pandas se suele importar con el alias de pd

	
import pandas as pd
print(pd.__version__)
Copy
	
1.0.1

3. Estructuras de datos de Pandaslink image 4

En Pandas existen dos tipos de estructuras de datos: las Series y los DataFrames

3.1. Serieslink image 5

El tipo de dato Serie es una matriz etiquetada unidimensional capaz de contener cualquier tipo de datos (enteros, cadenas, números de punto flotante, objetos Python, etc.). Está dividida en índices.

Para crear un tipo de dato Serie la forma más común es

serie = pd.Series(data, index=index)
      

Donde data puede ser

  • Un diccionario
  • Una lista o tupla
  • Un ndarray de Numpy
  • Un valor escalar

Como uno de los tipos de datos puede ser un ndarray de NumPy, importamos NumPy para poder usarlo

	
import numpy as np
Copy

3.1.1. Series desde un diccionariolink image 6

	
import numpy as np
diccionario = {"b": 1, "a": 0, "c": 2}
serie = pd.Series(diccionario)
serie
Copy
	
b 1
a 0
c 2
dtype: int64

Si se pasa un índice, se extraerán los valores de los datos correspondientes a las etiquetas del índice. Si no existen, se crean como NaN (not a number)

	
diccionario = {"b": 1, "a": 0, "c": 2}
serie = pd.Series(diccionario, index=["b", "c", "d", "a"])
serie
Copy
	
b 1.0
c 2.0
d NaN
a 0.0
dtype: float64

3.1.2. Series desde una lista o tuplalink image 7

Si los datos provienen de una lista o tupla y no se pasa ningún índice, se creará uno con valores [0, ..., len(data)-1]

	
serie = pd.Series([1, 2, 3, 4])
serie
Copy
	
0 1
1 2
2 3
3 4
dtype: int64

Si se pasa un índice, este debe tener la misma longitud que los datos

	
serie = pd.Series([1, 2, 3, 4], index=["a", "b", "c", "d"])
serie
Copy
	
a 1
b 2
c 3
d 4
dtype: int64

3.1.3. Series desde un ndarraylink image 8

Si los datos provienen de un ndarray y no se pasa ningún índice, se creará uno con valores [0, ..., len(data)-1]

	
serie = pd.Series(np.random.randn(5))
serie
Copy
	
0 1.267865
1 -0.877857
2 -0.138556
3 -0.132987
4 -0.827295
dtype: float64

Si se pasa un índice, este debe tener la misma longitud que los datos

	
serie = pd.Series(np.random.randn(5), index=["a", "b", "c", "d", "e"])
serie
Copy
	
a -1.091828
b -0.584243
c 0.220398
d 1.248923
e 1.652351
dtype: float64

3.1.4. Series desde un escalarlink image 9

Si se crea la serie desde un escalar, se creará con un único ítem

	
serie = pd.Series(5.0)
serie
Copy
	
0 5.0
dtype: float64

Si se quieren crear más ítems en la serie, hay que pasarle el índice con el número de ítems que se quiere, de esta manera todos los ítems tendrán el valor del escalar

	
serie = pd.Series(5.0, index=["a", "b", "c", "d", "e"])
serie
Copy
	
a 5.0
b 5.0
c 5.0
d 5.0
e 5.0
dtype: float64

3.1.5. Operaciones con Serieslink image 10

Al igual que con Numpy, podemos realizar operaciones con todos los elementos de una serie, sin tener que hacer una iteración por cada uno de ellos

	
serie = pd.Series(5.0, index=["a", "b", "c", "d", "e"])
print(f"serie:\n{serie}")
print(f"\nserie + serie =\n{serie + serie}")
Copy
	
serie:
a 5.0
b 5.0
c 5.0
d 5.0
e 5.0
dtype: float64
serie + serie =
a 10.0
b 10.0
c 10.0
d 10.0
e 10.0
dtype: float64
	
serie = pd.Series(5.0, index=["a", "b", "c", "d", "e"])
print(f"serie:\n{serie}")
print(f"\nexp(serie) =\n{np.exp(serie)}")
Copy
	
serie:
a 5.0
b 5.0
c 5.0
d 5.0
e 5.0
dtype: float64
exp(serie) =
a 148.413159
b 148.413159
c 148.413159
d 148.413159
e 148.413159
dtype: float64

Una diferencia entre Series y ndarrays es que las operaciones entre Series alinean automáticamente los datos según sus etiquetas. Por lo tanto, se pueden escribir cálculos sin tener en cuenta si las Series involucradas tienen las mismas etiquetas. Si no se encuentra una etiqueta en una Serie u otra, el resultado se marcará como faltante (NaN).

	
serie = pd.Series(5.0, index=["a", "b", "c", "d", "e"])
print(f"serie:\n{serie}")
print(f"\nserie[1:] + serie[:-1] =\n{serie[1:] + serie[:-1]}")
Copy
	
serie:
a 5.0
b 5.0
c 5.0
d 5.0
e 5.0
dtype: float64
serie[1:] + serie[:-1] =
a NaN
b 10.0
c 10.0
d 10.0
e NaN
dtype: float64

3.1.6. Atributo nombre de las Serieslink image 11

Uno de los atributos de las Series es name, el cual corresponde al nombre que tendrán cuando se añadan a un DataFrame. Por el camino contrario, cuando se obtiene una serie de un DataFrame, esta serie tendrá como nombre el que tenía en el DataFrame

	
serie = pd.Series(np.random.randn(5), name="aleatorio")
serie
Copy
	
0 -0.191009
1 -0.793151
2 -0.907747
3 -1.440508
4 -0.676419
Name: aleatorio, dtype: float64

Se puede cambiar el nombre de una serie mediante el método rename()

	
serie = serie.rename("random")
serie
Copy
	
0 -0.191009
1 -0.793151
2 -0.907747
3 -1.440508
4 -0.676419
Name: random, dtype: float64

3.2. DataFrameslink image 12

Un DataFrame es una estructura de datos etiquetada y bidimensional, con columnas de tipos potencialmente diferentes, es decir, en una columna puede haber datos de tipo entero, en otra columna datos de tipo string, etc. Puede pensar en ello como una hoja de cálculo o una tabla SQL, o un diccionario de objetos Series. Es el objeto pandas más utilizado. Al igual que las Series, los DataFrames aceptan muchos tipos diferentes de entrada:

Junto con los datos, opcionalmente puede pasar argumentos de índice (etiquetas de fila) y columnas (etiquetas de columna). Si pasa un índice y/o columnas, está garantizando el índice y/o columnas del DataFrame resultante. Por lo tanto, un diccionario de Series más un índice específico descartará todos los datos que no coincidan con el índice pasado

Si no se pasan las etiquetas de los ejes, se construirán a partir de los datos de entrada basándose en reglas de sentido común.

3.2.1. DataFrames desde un diccionario de Serieslink image 13

Si se pasa un diccionario con Series se creará el DataFrame con tantas columnas como Series tenga el diccionario

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0])
}
      
dataframe = pd.DataFrame(diccionario)
dataframe
      
Out[87]:
uno dos
0 1.0 4.0
1 2.0 5.0
2 3.0 6.0
3 NaN 7.0

Si cada una de las Series tiene índices definidos, el DataFrame resultante será la unión de estos índices

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0], index=["a", "b", "c"]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0], index=["a", "b", "c", "d"])
}
      
dataframe = pd.DataFrame(diccionario)
dataframe
      
Out[88]:
uno dos
a 1.0 4.0
b 2.0 5.0
c 3.0 6.0
d NaN 7.0
dataframe = pd.DataFrame(diccionario, index=["d", "b", "a"])
dataframe
      
Out[89]:
uno dos
d NaN 7.0
b 2.0 5.0
a 1.0 4.0

Si se le pasan las columnas aparecerán en el orden pasado

dataframe = pd.DataFrame(diccionario, columns=["dos", "tres"])
dataframe
      
Out[90]:
dos tres
a 4.0 NaN
b 5.0 NaN
c 6.0 NaN
d 7.0 NaN

3.2.2. DataFrames desde un diccionario de ndarrays o listaslink image 14

Todos los ndarrays o listas deben tener la misma longitud. Si se pasa un índice, también debe tener la misma longitud que los ndarrays o listas

diccionario = {
"uno": [1.0, 2.0, 3.0, 4.0],
"dos": [4.0, 3.0, 2.0, 1.0]
}
      
dataframe = pd.DataFrame(diccionario)
dataframe
      
Out[91]:
uno dos
0 1.0 4.0
1 2.0 3.0
2 3.0 2.0
3 4.0 1.0

3.2.3. DataFrames desde una matrizlink image 15

Si se pasa un índice, tiene que tener la misma longitud que el número de filas de la matriz y si se pasan las columnas, tienen que tener la misma longitud que las columnas de la matriz

matriz = np.array([[1, 3], [2, 2], [3, 1]])
      
dataframe = pd.DataFrame(matriz, index=["a", "b", "c"], columns=["columna1", "columna2"])
dataframe
      
Out[92]:
columna1 columna2
a 1 3
b 2 2
c 3 1

3.2.4. DataFrames desde una lista de diccionarioslink image 16

lista = [{"a": 1, "b": 2}, {"a": 5, "b": 10, "c": 20}]
      
dataframe = pd.DataFrame(lista)
dataframe
      
Out[93]:
a b c
0 1 2 NaN
1 5 10 20.0

3.2.5. DataFrames desde un diccionario de tuplaslink image 17

diccionario = {
("a", "b"): {("A", "B"): 1, ("A", "C"): 2},
("a", "a"): {("A", "C"): 3, ("A", "B"): 4},
("a", "c"): {("A", "B"): 5, ("A", "C"): 6},
("b", "a"): {("A", "C"): 7, ("A", "B"): 8},
("b", "b"): {("A", "D"): 9, ("A", "B"): 10},
}
      
dataframe = pd.DataFrame(diccionario)
dataframe
      
Out[94]:
a b
b a c a b
A B 1.0 4.0 5.0 8.0 10.0
C 2.0 3.0 6.0 7.0 NaN
D NaN NaN NaN NaN 9.0

3.2.6. DataFrames desde una Serielink image 18

El resultado será un DataFrame con el mismo índice que la Serie de entrada, y con una columna cuyo nombre es el nombre original de la Serie (solo si no se proporciona otro nombre de columna).

diccionario = {"b": 1, "a": 0, "c": 2}
      
serie = pd.Series(diccionario)
      
dataframe = pd.DataFrame(serie)
dataframe
      
Out[95]:
0
b 1
a 0
c 2

4. Exploración de un DataFramelink image 19

Cuando un DataFrame es muy grande no se puede representar entero

california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train
      
Out[102]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936 66900.0
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200 80100.0
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509 85700.0
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917 73400.0
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250 65500.0
... ... ... ... ... ... ... ... ... ...
16995 -124.26 40.58 52.0 2217.0 394.0 907.0 369.0 2.3571 111400.0
16996 -124.27 40.69 36.0 2349.0 528.0 1194.0 465.0 2.5179 79000.0
16997 -124.30 41.84 17.0 2677.0 531.0 1244.0 456.0 3.0313 103600.0
16998 -124.30 41.80 19.0 2672.0 552.0 1298.0 478.0 1.9797 85800.0
16999 -124.35 40.54 52.0 1820.0 300.0 806.0 270.0 3.0147 94600.0

17000 rows × 9 columns

Por lo que es muy útil tener métodos para explorarlo y obtener información de manera rápida.

4.1. Cabeza del DataFramelink image 20

Para ver las primeras filas y hacerse una idea de cómo es el DataFrame existe el método head(), que por defecto muestra las primeras 5 filas del DataFrame. Si se quiere ver un número distinto de filas introducirlo mediante el atributo n

california_housing_train.head(n=10)
      
Out[103]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936 66900.0
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200 80100.0
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509 85700.0
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917 73400.0
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250 65500.0
5 -114.58 33.63 29.0 1387.0 236.0 671.0 239.0 3.3438 74000.0
6 -114.58 33.61 25.0 2907.0 680.0 1841.0 633.0 2.6768 82400.0
7 -114.59 34.83 41.0 812.0 168.0 375.0 158.0 1.7083 48500.0
8 -114.59 33.61 34.0 4789.0 1175.0 3134.0 1056.0 2.1782 58400.0
9 -114.60 34.83 46.0 1497.0 309.0 787.0 271.0 2.1908 48100.0

4.2. Cola del DataFramelink image 21

Si lo que se quiere es ver las últimas filas se puede usar el método tail(), mediante el atributo n se elige cuántas filas mostrar

california_housing_train.tail()
      
Out[104]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
16995 -124.26 40.58 52.0 2217.0 394.0 907.0 369.0 2.3571 111400.0
16996 -124.27 40.69 36.0 2349.0 528.0 1194.0 465.0 2.5179 79000.0
16997 -124.30 41.84 17.0 2677.0 531.0 1244.0 456.0 3.0313 103600.0
16998 -124.30 41.80 19.0 2672.0 552.0 1298.0 478.0 1.9797 85800.0
16999 -124.35 40.54 52.0 1820.0 300.0 806.0 270.0 3.0147 94600.0

4.3. Información del DataFramelink image 22

Otro método muy útil es info() que nos da información del DataFrame

	
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0])
}
dataframe = pd.DataFrame(diccionario)
dataframe
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0], index=["a", "b", "c"]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0], index=["a", "b", "c", "d"])
}
dataframe = pd.DataFrame(diccionario)
dataframe
dataframe = pd.DataFrame(diccionario, index=["d", "b", "a"])
dataframe
dataframe = pd.DataFrame(diccionario, columns=["dos", "tres"])
dataframe
diccionario = {
"uno": [1.0, 2.0, 3.0, 4.0],
"dos": [4.0, 3.0, 2.0, 1.0]
}
dataframe = pd.DataFrame(diccionario)
dataframe
matriz = np.array([[1, 3], [2, 2], [3, 1]])
dataframe = pd.DataFrame(matriz, index=["a", "b", "c"], columns=["columna1", "columna2"])
dataframe
lista = [{"a": 1, "b": 2}, {"a": 5, "b": 10, "c": 20}]
dataframe = pd.DataFrame(lista)
dataframe
diccionario = {
("a", "b"): {("A", "B"): 1, ("A", "C"): 2},
("a", "a"): {("A", "C"): 3, ("A", "B"): 4},
("a", "c"): {("A", "B"): 5, ("A", "C"): 6},
("b", "a"): {("A", "C"): 7, ("A", "B"): 8},
("b", "b"): {("A", "D"): 9, ("A", "B"): 10},
}
dataframe = pd.DataFrame(diccionario)
dataframe
diccionario = {"b": 1, "a": 0, "c": 2}
serie = pd.Series(diccionario)
dataframe = pd.DataFrame(serie)
dataframe
california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train
california_housing_train.head(n=10)
california_housing_train.tail()
california_housing_train.info()
Copy
	
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 17000 entries, 0 to 16999
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 longitude 17000 non-null float64
1 latitude 17000 non-null float64
2 housing_median_age 17000 non-null float64
3 total_rooms 17000 non-null float64
4 total_bedrooms 17000 non-null float64
5 population 17000 non-null float64
6 households 17000 non-null float64
7 median_income 17000 non-null float64
8 median_house_value 17000 non-null float64
dtypes: float64(9)
memory usage: 1.2 MB

4.4. Filas y columnas DataFramelink image 23

Se pueden obtener los índices y las columnas de un DataFrame mediante los métodos index y columns

	
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0], index=["a", "b", "c"]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0], index=["a", "b", "c", "d"])
}
dataframe = pd.DataFrame(diccionario)
indices = dataframe.index
columnas = dataframe.columns
print(f"El DataFrame tiene los índices {indices}\n")
print(f"El DataFrame tiene las columnas {columnas}")
Copy
	
El DataFrame tiene los índices
Index(['a', 'b', 'c', 'd'], dtype='object')
El DataFrame tiene las columnas
Index(['uno', 'dos'], dtype='object')

4.5. Descripción del DataFramelink image 24

El método describe() muestra un resumen estadístico rápido de los datos del DataFrame

california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train.describe()
      
Out[107]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
count 17000.000000 17000.000000 17000.000000 17000.000000 17000.000000 17000.000000 17000.000000 17000.000000 17000.000000
mean -119.562108 35.625225 28.589353 2643.664412 539.410824 1429.573941 501.221941 3.883578 207300.912353
std 2.005166 2.137340 12.586937 2179.947071 421.499452 1147.852959 384.520841 1.908157 115983.764387
min -124.350000 32.540000 1.000000 2.000000 1.000000 3.000000 1.000000 0.499900 14999.000000
25% -121.790000 33.930000 18.000000 1462.000000 297.000000 790.000000 282.000000 2.566375 119400.000000
50% -118.490000 34.250000 29.000000 2127.000000 434.000000 1167.000000 409.000000 3.544600 180400.000000
75% -118.000000 37.720000 37.000000 3151.250000 648.250000 1721.000000 605.250000 4.767000 265000.000000
max -114.310000 41.950000 52.000000 37937.000000 6445.000000 35682.000000 6082.000000 15.000100 500001.000000

4.6. Ordenación del DataFramelink image 25

Se pueden ordenar alfabéticamente las filas de un DataFrame mediante el método sort_index()

california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train.sort_index().head()
      
Out[108]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936 66900.0
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200 80100.0
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509 85700.0
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917 73400.0
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250 65500.0

Como en este caso las filas ya estaban ordenadas, establecemos ascending=False para que el orden sea al revés

california_housing_train.sort_index(ascending=False).head()
      
Out[109]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
16999 -124.35 40.54 52.0 1820.0 300.0 806.0 270.0 3.0147 94600.0
16998 -124.30 41.80 19.0 2672.0 552.0 1298.0 478.0 1.9797 85800.0
16997 -124.30 41.84 17.0 2677.0 531.0 1244.0 456.0 3.0313 103600.0
16996 -124.27 40.69 36.0 2349.0 528.0 1194.0 465.0 2.5179 79000.0
16995 -124.26 40.58 52.0 2217.0 394.0 907.0 369.0 2.3571 111400.0

Si lo que se quiere es ordenar las columnas hay que introducir axis=1 ya que por defecto es 0

california_housing_train.sort_index(axis=1).head()
      
Out[110]:
households housing_median_age latitude longitude median_house_value median_income population total_bedrooms total_rooms
0 472.0 15.0 34.19 -114.31 66900.0 1.4936 1015.0 1283.0 5612.0
1 463.0 19.0 34.40 -114.47 80100.0 1.8200 1129.0 1901.0 7650.0
2 117.0 17.0 33.69 -114.56 85700.0 1.6509 333.0 174.0 720.0
3 226.0 14.0 33.64 -114.57 73400.0 3.1917 515.0 337.0 1501.0
4 262.0 20.0 33.57 -114.57 65500.0 1.9250 624.0 326.0 1454.0

Si lo que queremos es ordenar el DataFrame a través de una columna determinada, tenemos que usar el método sort_values() e indicarle la etiqueta de la columna sobre la que se quiere ordenar

california_housing_train.sort_values('median_house_value')
      
Out[111]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
568 -117.02 36.40 19.0 619.0 239.0 490.0 164.0 2.1000 14999.0
16643 -122.74 39.71 16.0 255.0 73.0 85.0 38.0 1.6607 14999.0
16801 -123.17 40.31 36.0 98.0 28.0 18.0 8.0 0.5360 14999.0
3226 -117.86 34.24 52.0 803.0 267.0 628.0 225.0 4.1932 14999.0
7182 -118.33 34.15 39.0 493.0 168.0 259.0 138.0 2.3667 17500.0
... ... ... ... ... ... ... ... ... ...
15834 -122.42 37.81 52.0 1314.0 317.0 473.0 250.0 4.3472 500001.0
7927 -118.40 33.87 38.0 2398.0 431.0 911.0 392.0 5.2319 500001.0
3546 -117.90 33.63 28.0 2370.0 352.0 832.0 347.0 7.1148 500001.0
7924 -118.40 33.88 35.0 1060.0 191.0 444.0 196.0 8.0015 500001.0
14011 -122.04 37.26 24.0 4973.0 709.0 1692.0 696.0 7.8627 500001.0

17000 rows × 9 columns

4.7. Estadísticas del DataFramelink image 26

Se pueden obtener estadísticas del DataFrame, como la media, la moda, la desviación estándar

	
california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train.describe()
california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train.sort_index().head()
california_housing_train.sort_index(ascending=False).head()
california_housing_train.sort_index(axis=1).head()
california_housing_train.sort_values('median_house_value')
california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
print(f"media:\n{california_housing_train.mean()}")
print(f" desviación estandar:\n{california_housing_train.std()}")
Copy
	
media:
longitude -119.562108
latitude 35.625225
housing_median_age 28.589353
total_rooms 2643.664412
total_bedrooms 539.410824
population 1429.573941
households 501.221941
median_income 3.883578
median_house_value 207300.912353
dtype: float64
desviación estandar:
longitude 2.005166
latitude 2.137340
housing_median_age 12.586937
total_rooms 2179.947071
total_bedrooms 421.499452
population 1147.852959
households 384.520841
median_income 1.908157
median_house_value 115983.764387
dtype: float64

Si se quieren obtener las estadísticas sobre las filas y no sobre las columnas hay que indicarlo mediante axis=1

	
california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
print(f"media:\n{california_housing_train.mean(axis=1)}")
print(f" desviación estandar:\n{california_housing_train.std(axis=1)}")
Copy
	
media:
0 8357.597067
1 10131.527778
2 9664.642322
3 8435.029078
4 7567.436111
...
16995 12806.408567
16996 9276.770878
16997 12049.507922
16998 10082.053300
16999 10863.022744
Length: 17000, dtype: float64
desviación estandar:
0 22026.612445
1 26352.939272
2 28514.316588
3 24366.754747
4 21730.014569
...
16995 36979.676899
16996 26158.006771
16997 34342.876792
16998 28408.152329
16999 31407.119788
Length: 17000, dtype: float64

Otra cosa útil que se puede obtener de los DataFrames es por ejemplo el número de veces que se repite cada ítem de una columna

	
california_housing_train["total_rooms"].value_counts()
Copy
	
1582.0 16
1527.0 15
1717.0 14
1471.0 14
1703.0 14
..
157.0 1
2760.0 1
458.0 1
10239.0 1
4068.0 1
Name: total_rooms, Length: 5533, dtype: int64

Por ejemplo, podemos ver que hay un total de 16 casas con 1582 habitaciones.

4.8. Memoria usadalink image 27

Podemos ver la memoria que usa el dataframe

	
california_housing_train.memory_usage(deep=True)
Copy
	
Index 128
longitude 136000
latitude 136000
housing_median_age 136000
total_rooms 136000
total_bedrooms 136000
population 136000
households 136000
median_income 136000
median_house_value 136000
dtype: int64

5. Adición de datoslink image 28

5.1. Adición de columnaslink image 29

Se pueden añadir columnas fácilmente como operaciones de otras columnas

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0])
}
      
dataframe = pd.DataFrame(diccionario)
      
dataframe["tres"] = dataframe["uno"] + dataframe["dos"]
dataframe["flag"] = dataframe["tres"] > 7.0
      
dataframe
      
Out[ ]:
uno dos tres flag
0 1.0 4.0 5.0 False
1 2.0 5.0 7.0 False
2 3.0 6.0 9.0 True
3 NaN 7.0 NaN False

También se pueden añadir columnas indicando qué valor tendrán todos sus ítems

dataframe["constante"] = 8.0
dataframe
      
Out[ ]:
uno dos tres flag constante
0 1.0 4.0 5.0 False 8.0
1 2.0 5.0 7.0 False 8.0
2 3.0 6.0 9.0 True 8.0
3 NaN 7.0 NaN False 8.0

Si se añade una Serie que no tiene el mismo número de índices que el DataFrame, esta se ajustará al número de índices del DataFrame

dataframe["Menos indices"] = dataframe["uno"][:2]
dataframe
      
Out[ ]:
uno dos tres flag constante Menos indices
0 1.0 4.0 5.0 False 8.0 1.0
1 2.0 5.0 7.0 False 8.0 2.0
2 3.0 6.0 9.0 True 8.0 NaN
3 NaN 7.0 NaN False 8.0 NaN

Con los métodos anteriores la columna se añadía al final, pero si se quiere añadir la columna en una posición determinada se puede usar el método insert(). Por ejemplo, si se quiere añadir una columna en la posición 3 (teniendo en cuenta que se empieza a contar desde la posición 0), que el nombre de la columna sea columna insertada y que su valor sea el doble que el de la columna tres, se haría de la siguiente manera

dataframe.insert(loc=3, column="columna insertada", value=dataframe["tres"]*2)
dataframe
      
Out[ ]:
uno dos tres columna insertada flag constante Menos indices
0 1.0 4.0 5.0 10.0 False 8.0 1.0
1 2.0 5.0 7.0 14.0 False 8.0 2.0
2 3.0 6.0 9.0 18.0 True 8.0 NaN
3 NaN 7.0 NaN NaN False 8.0 NaN

Si se quiere añadir más de una columna por comando se puede usar el método assign()

dataframe = dataframe.assign(
columna_asignada1 = dataframe["uno"] * dataframe["tres"],
columna_asignada2 = dataframe["dos"] * dataframe["tres"],
)
dataframe
      
Out[ ]:
uno dos tres columna insertada flag constante Menos indices columna_asignada1 columna_asignada2
0 1.0 4.0 5.0 10.0 False 8.0 1.0 5.0 20.0
1 2.0 5.0 7.0 14.0 False 8.0 2.0 14.0 35.0
2 3.0 6.0 9.0 18.0 True 8.0 NaN 27.0 54.0
3 NaN 7.0 NaN NaN False 8.0 NaN NaN NaN

5.2. Adición de filaslink image 30

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0])
}
      
dataframe = pd.DataFrame(diccionario)
      
dataframe.head()
      
Out[20]:
uno dos
0 1.0 4.0
1 2.0 5.0
2 3.0 6.0
3 NaN 7.0

Podemos añadir una fila al final con el método concat (que veremos más en detalle después)

diccionario = {
"uno": [10.0],
"dos": [20.0]
}
      
dataframe = pd.concat([dataframe, pd.DataFrame(diccionario)])
dataframe
      
Out[21]:
uno dos
0 1.0 4.0
1 2.0 5.0
2 3.0 6.0
3 NaN 7.0
0 10.0 20.0

Vemos que se ha añadido la columna al final, pero que tiene el índice cero, así que reordenamos los índices mediante el método reset_index(drop=True)

dataframe = dataframe.reset_index(drop=True)
dataframe
      
Out[23]:
index uno dos
0 0 1.0 4.0
1 1 2.0 5.0
2 2 3.0 6.0
3 3 NaN 7.0
4 0 10.0 20.0

6. Eliminación de datoslink image 31

6.1. Eliminación de columnaslink image 32

Se puede eliminar una columna determinada mediante el método pop()

dataframe.pop("constante")
dataframe
      
Out[ ]:
uno dos tres columna insertada flag Menos indices columna_asignada1 columna_asignada2
0 1.0 4.0 5.0 10.0 False 1.0 5.0 20.0
1 2.0 5.0 7.0 14.0 False 2.0 14.0 35.0
2 3.0 6.0 9.0 18.0 True NaN 27.0 54.0
3 NaN 7.0 NaN NaN False NaN NaN NaN

O mediante del

del dataframe["flag"]
dataframe
      
Out[ ]:
uno dos tres columna insertada Menos indices columna_asignada1 columna_asignada2
0 1.0 4.0 5.0 10.0 1.0 5.0 20.0
1 2.0 5.0 7.0 14.0 2.0 14.0 35.0
2 3.0 6.0 9.0 18.0 NaN 27.0 54.0
3 NaN 7.0 NaN NaN NaN NaN NaN

6.1. Eliminación de filaslink image 33

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]),
"dos": pd.Series([11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0]),
"tres": pd.Series([21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0])
}
      
dataframe = pd.DataFrame(diccionario)
      
dataframe.head()
      
Out[49]:
uno dos tres
0 1.0 11.0 21.0
1 2.0 12.0 22.0
2 3.0 13.0 23.0
3 4.0 14.0 24.0
4 5.0 15.0 25.0

Si queremos eliminar una fila, podemos usar el método drop, especificando su posición. Por ejemplo, si queremos eliminar la fila de la posición 1

dataframe = dataframe.drop(1)
dataframe
      
Out[50]:
uno dos tres
0 1.0 11.0 21.0
2 3.0 13.0 23.0
3 4.0 14.0 24.0
4 5.0 15.0 25.0
5 6.0 16.0 26.0
6 7.0 17.0 27.0
7 8.0 18.0 28.0
8 9.0 19.0 29.0
9 10.0 20.0 30.0

Si queremos eliminar la última fila

dataframe = dataframe.drop(len(dataframe)-1)
dataframe
      
Out[51]:
uno dos tres
0 1.0 11.0 21.0
2 3.0 13.0 23.0
3 4.0 14.0 24.0
4 5.0 15.0 25.0
5 6.0 16.0 26.0
6 7.0 17.0 27.0
7 8.0 18.0 28.0
9 10.0 20.0 30.0

Si lo que queremos es eliminar un rango de filas

dataframe = dataframe.drop(range(2, 5))
dataframe
      
Out[52]:
uno dos tres
0 1.0 11.0 21.0
5 6.0 16.0 26.0
6 7.0 17.0 27.0
7 8.0 18.0 28.0
9 10.0 20.0 30.0

Si lo que queremos es eliminar un conjunto de filas determinado

dataframe = dataframe.drop([5, 7, 9])
dataframe
      
Out[53]:
uno dos tres
0 1.0 11.0 21.0
6 7.0 17.0 27.0

Al igual que cuando añadimos filas, vemos que se han eliminado algunos índices, así que reordenamos los índices mediante el método reset_index(drop=True)

dataframe = dataframe.reset_index(drop=True)
dataframe
      
Out[54]:
uno dos tres
0 1.0 11.0 21.0
1 7.0 17.0 27.0

7. Operaciones sobre DataFrameslink image 34

Se pueden realizar operaciones sobre los DataFrames al igual que se podía hacer con Numpy

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]),
"dos": pd.Series([11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0]),
"tres": pd.Series([21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0])
}
      
dataframe = pd.DataFrame(diccionario)
      
dataframe.head()
      
Out[58]:
uno dos tres
0 1.0 11.0 21.0
1 2.0 12.0 22.0
2 3.0 13.0 23.0
3 4.0 14.0 24.0
4 5.0 15.0 25.0
dataframe[ ["uno", "dos", "tres"] ] * 2
      
Out[59]:
uno dos tres
0 2.0 22.0 42.0
1 4.0 24.0 44.0
2 6.0 26.0 46.0
3 8.0 28.0 48.0
4 10.0 30.0 50.0
5 12.0 32.0 52.0
6 14.0 34.0 54.0
7 16.0 36.0 56.0
8 18.0 38.0 58.0
9 20.0 40.0 60.0
np.exp(dataframe[ ["uno", "dos", "tres"] ])
      
Out[60]:
uno dos tres
0 2.718282 5.987414e+04 1.318816e+09
1 7.389056 1.627548e+05 3.584913e+09
2 20.085537 4.424134e+05 9.744803e+09
3 54.598150 1.202604e+06 2.648912e+10
4 148.413159 3.269017e+06 7.200490e+10
5 403.428793 8.886111e+06 1.957296e+11
6 1096.633158 2.415495e+07 5.320482e+11
7 2980.957987 6.565997e+07 1.446257e+12
8 8103.083928 1.784823e+08 3.931334e+12
9 22026.465795 4.851652e+08 1.068647e+13

Si se quiere realizar operaciones más complejas se puede utilizar el método apply()

	
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0])
}
dataframe = pd.DataFrame(diccionario)
dataframe["tres"] = dataframe["uno"] + dataframe["dos"]
dataframe["flag"] = dataframe["tres"] > 7.0
dataframe
dataframe["constante"] = 8.0
dataframe
dataframe["Menos indices"] = dataframe["uno"][:2]
dataframe
dataframe.insert(loc=3, column="columna insertada", value=dataframe["tres"]*2)
dataframe
dataframe = dataframe.assign(
columna_asignada1 = dataframe["uno"] * dataframe["tres"],
columna_asignada2 = dataframe["dos"] * dataframe["tres"],
)
dataframe
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0])
}
dataframe = pd.DataFrame(diccionario)
dataframe.head()
diccionario = {
"uno": [10.0],
"dos": [20.0]
}
dataframe = pd.concat([dataframe, pd.DataFrame(diccionario)])
dataframe
dataframe = dataframe.reset_index(drop=True)
dataframe
dataframe.pop("constante")
dataframe
del dataframe["flag"]
dataframe
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]),
"dos": pd.Series([11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0]),
"tres": pd.Series([21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0])
}
dataframe = pd.DataFrame(diccionario)
dataframe.head()
dataframe = dataframe.drop(1)
dataframe
dataframe = dataframe.drop(len(dataframe)-1)
dataframe
dataframe = dataframe.drop(range(2, 5))
dataframe
dataframe = dataframe.drop([5, 7, 9])
dataframe
dataframe = dataframe.reset_index(drop=True)
dataframe
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]),
"dos": pd.Series([11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0]),
"tres": pd.Series([21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0])
}
dataframe = pd.DataFrame(diccionario)
dataframe.head()
dataframe[ ["uno", "dos", "tres"] ] * 2
np.exp(dataframe[ ["uno", "dos", "tres"] ])
dataframe = dataframe.apply(lambda x: x.max() - x.min())
dataframe
Copy
	
uno 9.0
dos 9.0
tres 9.0
dtype: float64

Se ha aplicado una función lambda porque es una función sencilla, pero en caso de querer aplicar funciones más complejas, las podemos definir y aplicarlas

	
def funcion(x):
if x < 10:
return np.exp(x) - np.log(5*x) + np.sqrt(x)
elif x < 20:
return np.sin(x) + np.cos(x) + np.tan(x)
else:
return np.log(x) + np.log10(x) + np.log2(x)
dataframe = dataframe.apply(funcion)
dataframe
Copy
	
uno 8102.277265
dos 8102.277265
tres 8102.277265
dtype: float64

Utilizar el método apply en un dataframe es mucho más rápido que hacer un for por cada una de las líneas y realizar la operación

california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train.head()
      
Out[64]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936 66900.0
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200 80100.0
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509 85700.0
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917 73400.0
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250 65500.0

Vamos a calcular el porcentaje de dormitorios del total de habitaciones

california_housing_train["percent_bedrooms"] = None
%time california_housing_train["percent_bedrooms"] = california_housing_train.apply(lambda x: x["total_bedrooms"] / x["total_rooms"], axis=1)
california_housing_train.head()
      
CPU times: user 309 ms, sys: 86 µs, total: 309 ms
      Wall time: 309 ms
      
Out[74]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value percent_bedrooms
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936 66900.0 0.228617
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200 80100.0 0.248497
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509 85700.0 0.241667
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917 73400.0 0.224517
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250 65500.0 0.224209
california_housing_train["percent_bedrooms"] = None
%time for i in range(len(california_housing_train)): california_housing_train["percent_bedrooms"][i] = california_housing_train["total_bedrooms"][i] / california_housing_train["total_rooms"][i]
california_housing_train.head()
      
/home/wallabot/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: 
      A value is trying to be set on a copy of a slice from a DataFrame
      
      See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
        """Entry point for launching an IPython kernel.
      
CPU times: user 1.72 s, sys: 12 ms, total: 1.73 s
      Wall time: 1.72 s
      
Out[77]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value percent_bedrooms
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936 66900.0 0.228617
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200 80100.0 0.248497
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509 85700.0 0.241667
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917 73400.0 0.224517
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250 65500.0 0.224209

Con la función lambda ha tardado unos 300 ms, mientras que con el bucle for ha tardado más de 1 segundo

8. Transpuestalink image 35

Se puede hacer la transpuesta de un DataFrame mediante el método T

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0], index=["fila a", "fila b", "fila c"]),
"dos": pd.Series([4.0, 5.0, 6.0], index=["fila a", "fila b", "fila c"])
}
      
dataframe = pd.DataFrame(diccionario)
      
dataframe["tres"] = dataframe["uno"] + dataframe["dos"]
dataframe["flag"] = dataframe["tres"] > 7.0
      
dataframe.T
      
Out[ ]:
fila a fila b fila c
uno 1 2 3
dos 4 5 6
tres 5 7 9
flag False False True

9. Conversión a Numpylink image 36

Si se quiere convertir una Serie o DataFrame a NumPy se puede usar el método to_numpy() o usar la función np.asarray()

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0], index=["fila a", "fila b", "fila c"]),
"dos": pd.Series([4.0, 5.0, 6.0], index=["fila a", "fila b", "fila c"])
}
      
dataframe = pd.DataFrame(diccionario)
      
dataframe["tres"] = dataframe["uno"] + dataframe["dos"]
dataframe["flag"] = dataframe["tres"] > 7.0
      
dataframe
      
Out[ ]:
uno dos tres flag
fila a 1.0 4.0 5.0 False
fila b 2.0 5.0 7.0 False
fila c 3.0 6.0 9.0 True
	
california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train.head()
california_housing_train["percent_bedrooms"] = None
%time california_housing_train["percent_bedrooms"] = california_housing_train.apply(lambda x: x["total_bedrooms"] / x["total_rooms"], axis=1)
california_housing_train.head()
california_housing_train["percent_bedrooms"] = None
%time for i in range(len(california_housing_train)): california_housing_train["percent_bedrooms"][i] = california_housing_train["total_bedrooms"][i] / california_housing_train["total_rooms"][i]
california_housing_train.head()
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0], index=["fila a", "fila b", "fila c"]),
"dos": pd.Series([4.0, 5.0, 6.0], index=["fila a", "fila b", "fila c"])
}
dataframe = pd.DataFrame(diccionario)
dataframe["tres"] = dataframe["uno"] + dataframe["dos"]
dataframe["flag"] = dataframe["tres"] > 7.0
dataframe.T
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0], index=["fila a", "fila b", "fila c"]),
"dos": pd.Series([4.0, 5.0, 6.0], index=["fila a", "fila b", "fila c"])
}
dataframe = pd.DataFrame(diccionario)
dataframe["tres"] = dataframe["uno"] + dataframe["dos"]
dataframe["flag"] = dataframe["tres"] > 7.0
dataframe
matriz_np = dataframe.to_numpy()
matriz_np
Copy
	
CPU times: user 309 ms, sys: 86 µs, total: 309 ms
Wall time: 309 ms
/home/wallabot/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
"""Entry point for launching an IPython kernel.
array([[1.0, 4.0, 5.0, False],
[2.0, 5.0, 7.0, False],
[3.0, 6.0, 9.0, True]], dtype=object)
	
matriz_np = np.asarray(dataframe)
matriz_np
Copy
	
array([[1.0, 4.0, 5.0, False],
[2.0, 5.0, 7.0, False],
[3.0, 6.0, 9.0, True]], dtype=object)

Este ejemplo no es el más indicado, ya que mezcla números con booleanos, y como ya explicamos en el anterior post Cálculo matricial con NumPy, todos los elementos de un ndarray tienen que ser del mismo tipo. En este caso estamos mezclando números con booleanos, por lo que para solucionarlo NumPy los convierte todos a objetos Para solucionar esto nos quedamos solo con los números y los convertimos a un ndarray

	
matriz_np = dataframe[ ["uno", "dos", "tres"] ].to_numpy()
matriz_np, matriz_np.dtype
Copy
	
(array([[1., 4., 5.],
[2., 5., 7.],
[3., 6., 9.]]), dtype('float64'))

Ahora se puede ver que se ha creado un ndarray donde todos los datos son de tipo float

10. Lectura de datos de fuentes externaslink image 37

Una de las mayores fortalezas de Pandas es poder leer datos de archivos, por lo que no es necesario crearse un DataFrame con los datos que se quieren procesar, sino que se pueden leer de un archivo De la misma manera que se pueden crear DataFrames de archivos externos, también se pueden guardar DataFrames en archivos, para así crearte tu propio set de datos, configurarlo de la manera que quieras y guardarlo en un archivo para poder usarlo más adelante

En la siguiente tabla se muestran las funciones para leer y escribir archivos de distintos formatos

|Formato|Tipo de archivo|Función de lectura|Función de escritura||---|---|---|---| |texto|CSV|read_csv|to_csv| |texto|Fixed-Width Text File|read_fwf|| |texto|JSON|read_json|to_json| |texto|HTML|read_html|to_html| |texto|Local clipboard|read_clipboard|to_clipboard| |binary|MS Excel|read_excel|to_excel| |binary|OpenDocument|read_excel| |binary|HDF5 Format|read_hdf|to_hdf| |binary|Feather Format|read_feather|to_feather| |binary|Parquet Format|read_parquet|to_parquet| |binary|ORC Format|read_orc||binary|Msgpack|read_msgpack|to_msgpack| |binary|Stata|read_stata|to_stata| |binary|SAS|read_sas||binary|SPSS|read_spss||binary|Python Pickle Format|read_pickle|to_pickle| |SQL|SQL|read_sql|to_sql| |SQL|Google BigQuery|read_gbq|to_gbq|

11. Indexación en DataFrameslink image 38

Hay muchas maneras de indexar en los DataFrames,

fechas = pd.date_range('1/1/2000', periods=8)
dataframe = pd.DataFrame(np.random.randn(8, 4), index=fechas, columns=['A', 'B', 'C', 'D'])
      
dataframe
      
Out[56]:
A B C D
2000-01-01 -0.869298 -0.210502 0.477938 0.912121
2000-01-02 -0.502425 -1.897287 -0.084122 -1.203818
2000-01-03 -0.204297 0.711485 -1.271802 -0.138120
2000-01-04 1.512985 0.726718 0.960902 0.433124
2000-01-05 0.724005 -2.127668 0.674417 -0.297808
2000-01-06 -0.217175 -0.621172 0.668163 0.170576
2000-01-07 0.352484 0.260515 -1.576033 1.263213
2000-01-08 -0.032928 -0.648313 -0.622509 0.231683

11.1. Indexación de columnaslink image 39

Para seleccionar columnas dentro de un DataFrame lo podemos hacer seleccionando la columna entre corchetes [], o indicando la columna como si fuese un método del DataFrame

	
fechas = pd.date_range('1/1/2000', periods=8)
dataframe = pd.DataFrame(np.random.randn(8, 4), index=fechas, columns=['A', 'B', 'C', 'D'])
dataframe
dataframe['A']
Copy
	
2000-01-01 0.813153
2000-01-02 -0.244584
2000-01-03 0.125729
2000-01-04 0.352275
2000-01-05 -2.050976
2000-01-06 -0.312296
2000-01-07 0.897837
2000-01-08 0.271403
Freq: D, Name: A, dtype: float64
	
dataframe.A
Copy
	
2000-01-01 0.813153
2000-01-02 -0.244584
2000-01-03 0.125729
2000-01-04 0.352275
2000-01-05 -2.050976
2000-01-06 -0.312296
2000-01-07 0.897837
2000-01-08 0.271403
Freq: D, Name: A, dtype: float64

Si se quieren unas filas determinadas se pasan mediante una lista

dataframe[ ['A', 'B'] ]
      
Out[ ]:
A B
2000-01-01 -0.341962 0.639913
2000-01-02 0.507258 -0.942036
2000-01-03 -1.463557 1.041023
2000-01-04 1.781058 -1.849352
2000-01-05 0.318897 -0.229218
2000-01-06 0.362064 -0.193479
2000-01-07 -0.084632 -0.112474
2000-01-08 0.739424 0.253191

11.2. Indexación de filas por posicioneslink image 40

Se puede seleccionar un rango de filas de un DataFrame de la siguiente manera

dataframe[0:3]
      
Out[ ]:
A B C D
2000-01-01 0.813153 -0.869356 0.934293 0.338644
2000-01-02 -0.244584 0.536352 0.322248 0.238903
2000-01-03 0.125729 2.046910 -0.877466 -0.710034

Si solo se quiere seleccionar una sola fila, hay que indicar un rango de filas que incluya solo a esa, si por ejemplo se quiere seleccionar la fila número 1

dataframe[1:2]
      
Out[ ]:
A B C D
2000-01-02 -0.244584 0.536352 0.322248 0.238903

Otro método para seleccionar una fila por su posición es el método iloc[]

dataframe.iloc[0:3]
      
Out[ ]:
A B C D
2000-01-01 0.813153 -0.869356 0.934293 0.338644
2000-01-02 -0.244584 0.536352 0.322248 0.238903
2000-01-03 0.125729 2.046910 -0.877466 -0.710034

Si se quieren unas filas determinadas, se pasa una lista con sus posiciones

dataframe.iloc[ [0, 2, 4] ]
      
Out[ ]:
A B C D
2000-01-01 -0.341962 0.639913 0.765817 0.056692
2000-01-03 -1.463557 1.041023 -1.321715 2.822735
2000-01-05 0.318897 -0.229218 -1.095593 -0.186248

11.3. Indexación de filas por etiquetaslink image 41

Para seleccionar una fila por sus etiquetas podemos usar el método loc[]

	
dataframe[ ['A', 'B'] ]
dataframe[0:3]
dataframe[1:2]
dataframe.iloc[0:3]
dataframe.iloc[ [0, 2, 4] ]
dataframe.loc['2000-01-01']
Copy
	
A 0.813153
B -0.869356
C 0.934293
D 0.338644
Name: 2000-01-01 00:00:00, dtype: float64

Si se quiere seleccionar un rango de filas, podemos indexarlas mediante los dos puntos :

dataframe.loc['2000-01-01':'2000-01-03']
      
Out[ ]:
A B C D
2000-01-01 0.813153 -0.869356 0.934293 0.338644
2000-01-02 -0.244584 0.536352 0.322248 0.238903
2000-01-03 0.125729 2.046910 -0.877466 -0.710034

Si se quieren unas filas determinadas se pasan mediante una lista

dataframe.loc[ ['2000-01-01', '2000-01-03', '2000-01-05'] ]
      
Out[ ]:
A B C D
2000-01-01 -0.341962 0.639913 0.765817 0.056692
2000-01-03 -1.463557 1.041023 -1.321715 2.822735
2000-01-05 0.318897 -0.229218 -1.095593 -0.186248

11.4. Selección de una porción del DataFrame mediante posicioneslink image 42

dataframe.iloc[0:3, 0:2]
      
Out[ ]:
A B
2000-01-01 0.813153 -0.869356
2000-01-02 -0.244584 0.536352
2000-01-03 0.125729 2.046910

Si se quieren unas filas y columnas determinadas, se pasan listas con las posiciones deseadas

dataframe.iloc[ [0, 2, 4], [0, 2] ]
      
Out[ ]:
A C
2000-01-01 -0.341962 0.765817
2000-01-03 -1.463557 -1.321715
2000-01-05 0.318897 -1.095593

11.5. Selección de una porción del DataFrame mediante etiquetaslink image 43

dataframe.loc['2000-01-01':'2000-01-03', 'A':'B']
      
Out[ ]:
A B
2000-01-01 0.813153 -0.869356
2000-01-02 -0.244584 0.536352
2000-01-03 0.125729 2.046910

Si se quieren unas filas y columnas determinadas, se pasan listas con las etiquetas deseadas

dataframe.loc[ ['2000-01-01', '2000-01-03', '2000-01-05'], ['A', 'C'] ]
      
Out[ ]:
A C
2000-01-01 -0.341962 0.765817
2000-01-03 -1.463557 -1.321715
2000-01-05 0.318897 -1.095593

11.6. Indexación por función lambdalink image 44

Se pueden seleccionar datos de un DataFrame que cumplan una condición dada por una función lambda

dataframe.loc[lambda dataframe:2*dataframe['A']+5*np.exp(dataframe['B'])>0.2]
      
Out[58]:
A B C D
2000-01-01 -0.869298 -0.210502 0.477938 0.912121
2000-01-03 -0.204297 0.711485 -1.271802 -0.138120
2000-01-04 1.512985 0.726718 0.960902 0.433124
2000-01-05 0.724005 -2.127668 0.674417 -0.297808
2000-01-06 -0.217175 -0.621172 0.668163 0.170576
2000-01-07 0.352484 0.260515 -1.576033 1.263213
2000-01-08 -0.032928 -0.648313 -0.622509 0.231683

Como se puede ver, esta forma de indexación es muy potente

11.7. Indexación condicionallink image 45

Si no necesitamos funciones complejas para indexar, sino solo condicionales, podemos hacer

dataframe[dataframe['A']>0.2]
      
Out[61]:
A B C D
2000-01-04 1.512985 0.726718 0.960902 0.433124
2000-01-05 0.724005 -2.127668 0.674417 -0.297808
2000-01-07 0.352484 0.260515 -1.576033 1.263213

Podemos hacer múltiples condiciones

dataframe[(dataframe['A']>0.2) & (dataframe['B']>0.2)]
      
Out[69]:
A B C D
2000-01-04 1.512985 0.726718 0.960902 0.433124
2000-01-07 0.352484 0.260515 -1.576033 1.263213

11.8. Indexación aleatorialink image 46

Mediante el método sample() obtendremos una fila aleatoria del DataFrame

dataframe.sample()
      
Out[ ]:
A B C D
2000-01-06 -0.312296 0.129097 -0.991085 1.704535

Si queremos más de una muestra lo indicamos con el atributo n

dataframe.sample(n=3)
      
Out[ ]:
A B C D
2000-01-08 0.271403 1.527116 0.144970 1.175728
2000-01-01 0.813153 -0.869356 0.934293 0.338644
2000-01-03 0.125729 2.046910 -0.877466 -0.710034

Si lo que se quiere son columnas aleatorias hay que indicarlo mediante axis=1

dataframe.sample(axis=1)
      
Out[ ]:
D
2000-01-01 0.338644
2000-01-02 0.238903
2000-01-03 -0.710034
2000-01-04 0.504410
2000-01-05 -1.601926
2000-01-06 1.704535
2000-01-07 -0.584860
2000-01-08 1.175728

Si se quiere un único item del DataFrame hay que llamar dos veces al método sample()

dataframe.sample(axis=1).sample()
      
Out[ ]:
D
2000-01-05 -1.601926

12. Unión de DataFrameslink image 47

12.1. Concatenación de DataFrameslink image 48

Para concatenar varios DataFrames usamos el método concat(), donde se le pasará una lista con los DataFrames que se quiere unir

	
dataframe.loc['2000-01-01':'2000-01-03']
dataframe.loc[ ['2000-01-01', '2000-01-03', '2000-01-05'] ]
dataframe.iloc[0:3, 0:2]
dataframe.iloc[ [0, 2, 4], [0, 2] ]
dataframe.loc['2000-01-01':'2000-01-03', 'A':'B']
dataframe.loc[ ['2000-01-01', '2000-01-03', '2000-01-05'], ['A', 'C'] ]
dataframe.loc[lambda dataframe:2*dataframe['A']+5*np.exp(dataframe['B'])>0.2]
dataframe[dataframe['A']>0.2]
dataframe[(dataframe['A']>0.2) & (dataframe['B']>0.2)]
dataframe.sample()
dataframe.sample(n=3)
dataframe.sample(axis=1)
dataframe.sample(axis=1).sample()
dataframe1 = pd.DataFrame(
{
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
})
dataframe2 = pd.DataFrame(
{
"A": ["A4", "A5", "A6", "A7"],
"B": ["B4", "B5", "B6", "B7"],
"C": ["C4", "C5", "C6", "C7"],
"D": ["D4", "D5", "D6", "D7"],
})
dataframe3 = pd.DataFrame(
{
"A": ["A8", "A9", "A10", "A11"],
"B": ["B8", "B9", "B10", "B11"],
"C": ["C8", "C9", "C10", "C11"],
"D": ["D8", "D9", "D10", "D11"],
})
dataframe = pd.concat([dataframe1, dataframe2, dataframe3])
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"dataframe3:\n{dataframe3}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
dataframe2:
A B C D
0 A4 B4 C4 D4
1 A5 B5 C5 D5
2 A6 B6 C6 D6
3 A7 B7 C7 D7
dataframe3:
A B C D
0 A8 B8 C8 D8
1 A9 B9 C9 D9
2 A10 B10 C10 D10
3 A11 B11 C11 D11
dataframe:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
0 A4 B4 C4 D4
1 A5 B5 C5 D5
2 A6 B6 C6 D6
3 A7 B7 C7 D7
0 A8 B8 C8 D8
1 A9 B9 C9 D9
2 A10 B10 C10 D10
3 A11 B11 C11 D11

Como se puede ver, los índices 0, 1, 2 y 3 se repiten, porque cada dataframe tiene esos índices. Para que no ocurra esto hay que usar el parámetro ignore_index=True

	
dataframe = pd.concat([dataframe1, dataframe2, dataframe3], ignore_index=True)
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"dataframe3:\n{dataframe3}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
dataframe2:
A B C D
0 A4 B4 C4 D4
1 A5 B5 C5 D5
2 A6 B6 C6 D6
3 A7 B7 C7 D7
dataframe3:
A B C D
0 A8 B8 C8 D8
1 A9 B9 C9 D9
2 A10 B10 C10 D10
3 A11 B11 C11 D11
dataframe:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
4 A4 B4 C4 D4
5 A5 B5 C5 D5
6 A6 B6 C6 D6
7 A7 B7 C7 D7
8 A8 B8 C8 D8
9 A9 B9 C9 D9
10 A10 B10 C10 D10
11 A11 B11 C11 D11

concat

Si se hubiera querido hacer la concatenación a lo largo de las columnas habría que haber introducido la variable axis=1

	
dataframe = pd.concat([dataframe1, dataframe2, dataframe3], axis=1)
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"dataframe3:\n{dataframe3}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
dataframe2:
A B C D
0 A4 B4 C4 D4
1 A5 B5 C5 D5
2 A6 B6 C6 D6
3 A7 B7 C7 D7
dataframe3:
A B C D
0 A8 B8 C8 D8
1 A9 B9 C9 D9
2 A10 B10 C10 D10
3 A11 B11 C11 D11
dataframe:
A B C D A B C D A B C D
0 A0 B0 C0 D0 A4 B4 C4 D4 A8 B8 C8 D8
1 A1 B1 C1 D1 A5 B5 C5 D5 A9 B9 C9 D9
2 A2 B2 C2 D2 A6 B6 C6 D6 A10 B10 C10 D10
3 A3 B3 C3 D3 A7 B7 C7 D7 A11 B11 C11 D11

12.1.1. Intersección de concatenaciónlink image 49

Hay dos maneras de hacer la concatenación, cogiendo todos los índices de los DataFrames o cogiendo solo los que coinciden, esto se determina mediante la variable join, que admite los valores 'outer' (por defecto) (coge todos los índices) o 'inner' (solo los que coinciden)

Veamos un ejemplo de 'outer'

	
dataframe1 = pd.DataFrame(
{
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
},
index=[0, 1, 2, 3])
dataframe4 = pd.DataFrame(
{
"B": ["B2", "B3", "B6", "B7"],
"D": ["D2", "D3", "D6", "D7"],
"F": ["F2", "F3", "F6", "F7"],
},index=[2, 3, 6, 7])
dataframe = pd.concat([dataframe1, dataframe4], axis=1)
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe4}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
dataframe2:
B D F
2 B2 D2 F2
3 B3 D3 F3
6 B6 D6 F6
7 B7 D7 F7
dataframe:
A B C D B D F
0 A0 B0 C0 D0 NaN NaN NaN
1 A1 B1 C1 D1 NaN NaN NaN
2 A2 B2 C2 D2 B2 D2 F2
3 A3 B3 C3 D3 B3 D3 F3
6 NaN NaN NaN NaN B6 D6 F6
7 NaN NaN NaN NaN B7 D7 F7

outlier

Veamos un ejemplo de 'inner'

	
dataframe = pd.concat([dataframe1, dataframe4], axis=1, join="inner")
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe4}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
dataframe2:
B D F
2 B2 D2 F2
3 B3 D3 F3
6 B6 D6 F6
7 B7 D7 F7
dataframe:
A B C D B D F
2 A2 B2 C2 D2 B2 D2 F2
3 A3 B3 C3 D3 B3 D3 F3

inner

12.2. Merge de DataFrameslink image 50

Antes hemos creado un dataframe nuevo con la unión de varios dataframes, ahora podemos completar un dataframe con otro, para ello usamos merge, pasándole el parámetro on, sobre qué columna queremos que se haga el merge

	
dataframe1 = pd.DataFrame(
{
"Key": ["K0", "K1", "K2", "K3"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
})
dataframe2 = pd.DataFrame(
{
"Key": ["K0", "K1", "K2", "K3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
})
dataframe = dataframe1.merge(dataframe2, on="Key")
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
Key A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 B3
dataframe2:
Key C D
0 K0 C0 D0
1 K1 C1 D1
2 K2 C2 D2
3 K3 C3 D3
dataframe:
Key A B C D
0 K0 A0 B0 C0 D0
1 K1 A1 B1 C1 D1
2 K2 A2 B2 C2 D2
3 K3 A3 B3 C3 D3

En este caso los dos dataframes tenían una llave que se llamaba igual (Key), pero en el caso de tener dataframes, en los que su llave se llame de otra forma podemos usar los parámetros left_on y right_on

	
dataframe1 = pd.DataFrame(
{
"Key1": ["K0", "K1", "K2", "K3"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
})
dataframe2 = pd.DataFrame(
{
"Key2": ["K0", "K1", "K2", "K3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
})
dataframe = dataframe1.merge(dataframe2, left_on="Key1", right_on="Key2")
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
Key1 A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 B3
dataframe2:
Key2 C D
0 K0 C0 D0
1 K1 C1 D1
2 K2 C2 D2
3 K3 C3 D3
dataframe:
Key1 A B Key2 C D
0 K0 A0 B0 K0 C0 D0
1 K1 A1 B1 K1 C1 D1
2 K2 A2 B2 K2 C2 D2
3 K3 A3 B3 K3 C3 D3

En el caso en el que una de las claves no coincida no se hará el merge sobre esa clave

	
dataframe1 = pd.DataFrame(
{
"Key1": ["K0", "K1", "K2", "K3"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
})
dataframe2 = pd.DataFrame(
{
"Key2": ["K0", "K1", "K2", np.nan],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
})
dataframe = dataframe1.merge(dataframe2, left_on="Key1", right_on="Key2")
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
Key1 A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 B3
dataframe2:
Key2 C D
0 K0 C0 D0
1 K1 C1 D1
2 K2 C2 D2
3 NaN C3 D3
dataframe:
Key1 A B Key2 C D
0 K0 A0 B0 K0 C0 D0
1 K1 A1 B1 K1 C1 D1
2 K2 A2 B2 K2 C2 D2

Para cambiar este comportamiento podemos usar el parámetro how, que por defecto tiene el valor inner, pero le podemos pasar el valor left, right y outer

	
dataframe1 = pd.DataFrame(
{
"Key1": ["K0", "K1", "K2", "K3"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
})
dataframe2 = pd.DataFrame(
{
"Key2": ["K0", "K1", "K2", np.nan],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
})
dataframe_inner = dataframe1.merge(dataframe2, left_on="Key1", right_on="Key2", how="inner")
dataframe_left = dataframe1.merge(dataframe2, left_on="Key1", right_on="Key2", how="left")
dataframe_right = dataframe1.merge(dataframe2, left_on="Key1", right_on="Key2", how="right")
dataframe_outer = dataframe1.merge(dataframe2, left_on="Key1", right_on="Key2", how="outer")
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"\ndataframe inner:\n{dataframe_inner}")
print(f"\ndataframe left:\n{dataframe_left}")
print(f"\ndataframe right:\n{dataframe_right}")
print(f"\ndataframe outer:\n{dataframe_outer}")
Copy
	
dataframe1:
Key1 A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 B3
dataframe2:
Key2 C D
0 K0 C0 D0
1 K1 C1 D1
2 K2 C2 D2
3 NaN C3 D3
dataframe inner:
Key1 A B Key2 C D
0 K0 A0 B0 K0 C0 D0
1 K1 A1 B1 K1 C1 D1
2 K2 A2 B2 K2 C2 D2
dataframe left:
Key1 A B Key2 C D
0 K0 A0 B0 K0 C0 D0
1 K1 A1 B1 K1 C1 D1
2 K2 A2 B2 K2 C2 D2
3 K3 A3 B3 NaN NaN NaN
dataframe right:
Key1 A B Key2 C D
0 K0 A0 B0 K0 C0 D0
1 K1 A1 B1 K1 C1 D1
2 K2 A2 B2 K2 C2 D2
3 NaN NaN NaN NaN C3 D3
dataframe outer:
Key1 A B Key2 C D
0 K0 A0 B0 K0 C0 D0
1 K1 A1 B1 K1 C1 D1
2 K2 A2 B2 K2 C2 D2
3 K3 A3 B3 NaN NaN NaN
4 NaN NaN NaN NaN C3 D3

Como se puede ver, cuando se elige left solo se añaden los valores del dataframe de la izquierda y cuando se elige right, los valores del dataframe de la derecha

12.3. Join de dataframeslink image 51

La última herramienta de unión de dataframes es join. Es similar a merge, solo que en vez de buscar similitudes en función de columnas especificadas, las busca en función de los índices.

	
dataframe1 = pd.DataFrame(
{
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
},
index=["K0", "K1", "K2", "K3"])
dataframe2 = pd.DataFrame(
{
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
},
index=["K0", "K1", "K2", "K3"])
dataframe = dataframe1.join(dataframe2)
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"\ndataframe:\n{dataframe}")
Copy
	
dataframe1:
A B
K0 A0 B0
K1 A1 B1
K2 A2 B2
K3 A3 B3
dataframe2:
C D
K0 C0 D0
K1 C1 D1
K2 C2 D2
K3 C3 D3
dataframe:
A B C D
K0 A0 B0 C0 D0
K1 A1 B1 C1 D1
K2 A2 B2 C2 D2
K3 A3 B3 C3 D3

En este caso, los índices son iguales, pero cuando son distintos podemos especificar la manera de unir los dataframes mediante el parámetro how, que por defecto tiene el valor inner, pero puede tener el valor left, right y outer

	
dataframe1 = pd.DataFrame(
{
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
},
index=["K0", "K1", "K2", "K3"])
dataframe2 = pd.DataFrame(
{
"C": ["C0", "C2", "C3", "C4"],
"D": ["D0", "D2", "D3", "D4"],
},
index=["K0", "K2", "K3", "K4"])
dataframe_inner = dataframe1.join(dataframe2, how="inner")
dataframe_left = dataframe1.join(dataframe2, how="left")
dataframe_right = dataframe1.join(dataframe2, how="right")
dataframe_outer = dataframe1.join(dataframe2, how="outer")
print(f"dataframe1:\n{dataframe1}")
print(f"dataframe2:\n{dataframe2}")
print(f"\ndataframe inner:\n{dataframe_inner}")
print(f"\ndataframe left:\n{dataframe_left}")
print(f"\ndataframe rigth:\n{dataframe_right}")
print(f"\ndataframe outer:\n{dataframe_outer}")
Copy
	
dataframe1:
A B
K0 A0 B0
K1 A1 B1
K2 A2 B2
K3 A3 B3
dataframe2:
C D
K0 C0 D0
K2 C2 D2
K3 C3 D3
K4 C4 D4
dataframe:
A B C D
K0 A0 B0 C0 D0
K2 A2 B2 C2 D2
K3 A3 B3 C3 D3
dataframe:
A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
K3 A3 B3 C3 D3
dataframe:
A B C D
K0 A0 B0 C0 D0
K2 A2 B2 C2 D2
K3 A3 B3 C3 D3
K4 NaN NaN C4 D4
dataframe:
A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
K3 A3 B3 C3 D3
K4 NaN NaN C4 D4

13. Datos faltantes (NaN)link image 52

En un DataFrame puede haber algunos datos faltantes, Pandas los representa como np.nan

diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0])
}
      
dataframe = pd.DataFrame(diccionario)
dataframe
      
Out[ ]:
uno dos
0 1.0 4.0
1 2.0 5.0
2 3.0 6.0
3 NaN 7.0

13.1. Eliminación de las filas con datos faltanteslink image 53

Para no tener filas con datos faltantes, se pueden eliminar estas

dataframe.dropna(how="any")
      
Out[ ]:
uno dos
0 1.0 4.0
1 2.0 5.0
2 3.0 6.0

13.2. Eliminación de las columnas con datos faltanteslink image 54

dataframe.dropna(axis=1, how='any')
      
Out[ ]:
dos
0 4.0
1 5.0
2 6.0
3 7.0

13.3. Máscara booleana con las posiciones faltanteslink image 55

pd.isna(dataframe)
      
Out[ ]:
uno dos
0 False False
1 False False
2 False False
3 True False

13.4. Rellenado de los datos faltanteslink image 56

dataframe.fillna(value=5.5, inplace=True)
dataframe
      
Out[ ]:
uno dos
0 1.0 4.0
1 2.0 5.0
2 3.0 6.0
3 5.5 7.0

Tip: Poniendo la variable inplace=True se modifica el DataFrame sobre el que se está operando, así no hace falta escribir dataframe = dataframe.fillna(value=5.5)

14. Series temporaleslink image 57

Pandas ofrece la posibilidad de trabajar con series temporales. Por ejemplo, creamos una Serie de 100 datos aleatorios cada segundo desde el 01/01/2021

	
diccionario = {
"uno": pd.Series([1.0, 2.0, 3.0]),
"dos": pd.Series([4.0, 5.0, 6.0, 7.0])
}
dataframe = pd.DataFrame(diccionario)
dataframe
dataframe.dropna(how="any")
dataframe.dropna(axis=1, how='any')
pd.isna(dataframe)
dataframe.fillna(value=5.5, inplace=True)
dataframe
indices = pd.date_range("1/1/2021", periods=100, freq="S")
datos = np.random.randint(0, 500, len(indices))
serie_temporal = pd.Series(datos, index=indices)
serie_temporal
Copy
	
2021-01-01 00:00:00 241
2021-01-01 00:00:01 14
2021-01-01 00:00:02 190
2021-01-01 00:00:03 407
2021-01-01 00:00:04 94
...
2021-01-01 00:01:35 275
2021-01-01 00:01:36 56
2021-01-01 00:01:37 448
2021-01-01 00:01:38 151
2021-01-01 00:01:39 316
Freq: S, Length: 100, dtype: int64

Esta funcionalidad de Pandas es muy potente, por ejemplo, podemos tener un conjunto de datos en unas horas determinadas de un huso horario y cambiarlas a otro huso

	
horas = pd.date_range("3/6/2021 00:00", periods=10, freq="H")
datos = np.random.randn(len(horas))
serie_horaria = pd.Series(datos, horas)
serie_horaria
Copy
	
2021-03-06 00:00:00 -0.853524
2021-03-06 01:00:00 -1.355372
2021-03-06 02:00:00 -1.267503
2021-03-06 03:00:00 -1.155787
2021-03-06 04:00:00 0.730935
2021-03-06 05:00:00 1.435957
2021-03-06 06:00:00 0.460912
2021-03-06 07:00:00 0.723451
2021-03-06 08:00:00 -0.853337
2021-03-06 09:00:00 0.456359
Freq: H, dtype: float64

Localizamos los datos en un huso horario

	
serie_horaria_utc = serie_horaria.tz_localize("UTC")
serie_horaria_utc
Copy
	
2021-03-06 00:00:00+00:00 -0.853524
2021-03-06 01:00:00+00:00 -1.355372
2021-03-06 02:00:00+00:00 -1.267503
2021-03-06 03:00:00+00:00 -1.155787
2021-03-06 04:00:00+00:00 0.730935
2021-03-06 05:00:00+00:00 1.435957
2021-03-06 06:00:00+00:00 0.460912
2021-03-06 07:00:00+00:00 0.723451
2021-03-06 08:00:00+00:00 -0.853337
2021-03-06 09:00:00+00:00 0.456359
Freq: H, dtype: float64

Y ahora las podemos cambiar a otro uso

	
serie_horaria_US = serie_horaria_utc.tz_convert("US/Eastern")
serie_horaria_US
Copy
	
2021-03-05 19:00:00-05:00 -0.853524
2021-03-05 20:00:00-05:00 -1.355372
2021-03-05 21:00:00-05:00 -1.267503
2021-03-05 22:00:00-05:00 -1.155787
2021-03-05 23:00:00-05:00 0.730935
2021-03-06 00:00:00-05:00 1.435957
2021-03-06 01:00:00-05:00 0.460912
2021-03-06 02:00:00-05:00 0.723451
2021-03-06 03:00:00-05:00 -0.853337
2021-03-06 04:00:00-05:00 0.456359
Freq: H, dtype: float64

15. Datos categóricoslink image 58

Pandas ofrece la posibilidad de añadir datos categóricos en un DataFrame. Supongamos el siguiente DataFrame

dataframe = pd.DataFrame(
{"id": [1, 2, 3, 4, 5, 6], "raw_grade": ["a", "b", "b", "a", "a", "e"]}
)
      
dataframe
      
Out[2]:
id raw_grade
0 1 a
1 2 b
2 3 b
3 4 a
4 5 a
5 6 e

Podemos convertir los datos de la columna raw_grade a datos categóricos mediante el método astype()

dataframe['grade'] = dataframe["raw_grade"].astype("category")
      
dataframe
      
Out[3]:
id raw_grade grade
0 1 a a
1 2 b b
2 3 b b
3 4 a a
4 5 a a
5 6 e e

Las columnas raw_grade y grade parecen iguales, pero si vemos la información del DataFrame podemos ver que no es así

	
dataframe = pd.DataFrame(
{"id": [1, 2, 3, 4, 5, 6], "raw_grade": ["a", "b", "b", "a", "a", "e"]}
)
dataframe
dataframe['grade'] = dataframe["raw_grade"].astype("category")
dataframe
dataframe.info()
Copy
	
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 6 non-null int64
1 raw_grade 6 non-null object
2 grade 6 non-null category
dtypes: category(1), int64(1), object(1)
memory usage: 334.0+ bytes

Se puede ver que la columna grade es de tipo categórico

Podemos ver las categorías de los tipos de datos categóricos mediante el método cat.categories()

	
dataframe["grade"].cat.categories
Copy
	
Index(['a', 'b', 'e'], dtype='object')

Podemos también renombrar las categorías con el mismo método, pero introduciendo una lista con las nuevas categorías.

dataframe["grade"].cat.categories = ["very good", "good", "very bad"]
dataframe
      
Out[7]:
id raw_grade grade
0 1 a very good
1 2 b good
2 3 b good
3 4 a very good
4 5 a very good
5 6 e very bad

Pandas nos da la posibilidad de codificar numéricamente los datos categóricos mediante el método get_dummies

pd.get_dummies(dataframe["grade"])
      
Out[8]:
very good good very bad
0 1 0 0
1 0 1 0
2 0 1 0
3 1 0 0
4 1 0 0
5 0 0 1

16. Groupbylink image 59

Podemos agrupar los dataframes por valores de alguna de las columnas. Volvamos a cargar el dataframe con el valor de las casas de California.

california_housing_train = pd.read_csv("https://raw.githubusercontent.com/maximofn/portafolio/main/posts/california_housing_train.csv")
california_housing_train.head()
      
Out[43]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
0 -114.31 34.19 15.0 5612.0 1283.0 1015.0 472.0 1.4936 66900.0
1 -114.47 34.40 19.0 7650.0 1901.0 1129.0 463.0 1.8200 80100.0
2 -114.56 33.69 17.0 720.0 174.0 333.0 117.0 1.6509 85700.0
3 -114.57 33.64 14.0 1501.0 337.0 515.0 226.0 3.1917 73400.0
4 -114.57 33.57 20.0 1454.0 326.0 624.0 262.0 1.9250 65500.0

Ahora podemos agrupar los datos por alguna de las columnas, por ejemplo, agrupemos las casas en función del número de años y veamos cuántas casas hay de cada edad con count

california_housing_train.groupby("housing_median_age").count().head()
      
Out[8]:
longitude latitude total_rooms total_bedrooms population households median_income median_house_value
housing_median_age
1.0 2 2 2 2 2 2 2 2
2.0 49 49 49 49 49 49 49 49
3.0 46 46 46 46 46 46 46 46
4.0 161 161 161 161 161 161 161 161
5.0 199 199 199 199 199 199 199 199

Como vemos en todas las columnas, obtenemos el mismo valor, que es el número de casas que hay con una determinada edad, pero podemos saber la media del valor de cada columna con mean

california_housing_train.groupby("housing_median_age").mean().head()
      
Out[9]:
longitude latitude total_rooms total_bedrooms population households median_income median_house_value
housing_median_age
1.0 -121.465000 37.940000 2158.000000 335.500000 637.000000 190.000000 4.756800 190250.000000
2.0 -119.035306 35.410816 5237.102041 871.448980 2005.224490 707.122449 5.074237 229438.836735
3.0 -118.798478 35.164783 6920.326087 1190.826087 2934.673913 1030.413043 5.572013 239450.043478
4.0 -118.805093 34.987764 6065.614907 1068.192547 2739.956522 964.291925 5.196055 230054.105590
5.0 -118.789497 35.095327 4926.261307 910.924623 2456.979899 826.768844 4.732460 211035.708543

Podemos obtener varias medidas de cada edad mediante el comando agg (aggregation), pasándole las medidas que queremos mediante una lista, por ejemplo veamos el mínimo, el máximo y la media de cada columna para cada edad de casa

california_housing_train.groupby("housing_median_age").agg(['min', 'max', 'mean']).head()
      
Out[10]:
longitude latitude total_rooms total_bedrooms ... population households median_income median_house_value
min max mean min max mean min max mean min ... mean min max mean min max mean min max mean
housing_median_age
1.0 -122.00 -120.93 -121.465000 37.65 38.23 37.940000 2062.0 2254.0 2158.000000 328.0 ... 637.000000 112.0 268.0 190.000000 4.2500 5.2636 4.756800 189200.0 191300.0 190250.000000
2.0 -122.51 -115.80 -119.035306 33.16 40.58 35.410816 96.0 21897.0 5237.102041 18.0 ... 2005.224490 16.0 2873.0 707.122449 1.9667 10.1531 5.074237 47500.0 500001.0 229438.836735
3.0 -122.33 -115.60 -118.798478 32.87 38.77 35.164783 475.0 21060.0 6920.326087 115.0 ... 2934.673913 123.0 3112.0 1030.413043 2.1187 11.5199 5.572013 83200.0 500001.0 239450.043478
4.0 -122.72 -116.76 -118.805093 32.65 39.00 34.987764 2.0 37937.0 6065.614907 2.0 ... 2739.956522 2.0 5189.0 964.291925 0.5360 13.4883 5.196055 42500.0 500001.0 230054.105590
5.0 -122.55 -115.55 -118.789497 32.55 40.60 35.095327 111.0 25187.0 4926.261307 21.0 ... 2456.979899 20.0 3886.0 826.768844 0.7526 12.6320 4.732460 50000.0 500001.0 211035.708543

5 rows × 24 columns

Podemos especificar sobre qué columnas queremos realizar ciertos cálculos mediante el paso de un diccionario, donde las claves serán las columnas sobre las que queremos realizar cálculos y los valores serán listas con los cálculos

california_housing_train.groupby("housing_median_age").agg({'total_rooms': ['min', 'max', 'mean'], 'total_bedrooms': ['min', 'max', 'mean', 'median']}).head()
      
Out[12]:
total_rooms total_bedrooms
min max mean min max mean median
housing_median_age
1.0 2062.0 2254.0 2158.000000 328.0 343.0 335.500000 335.5
2.0 96.0 21897.0 5237.102041 18.0 3513.0 871.448980 707.0
3.0 475.0 21060.0 6920.326087 115.0 3559.0 1190.826087 954.0
4.0 2.0 37937.0 6065.614907 2.0 5471.0 1068.192547 778.0
5.0 111.0 25187.0 4926.261307 21.0 4386.0 910.924623 715.0

Podemos agrupar por más de una columna, para ello, hay que pasar las columnas en una lista

california_housing_train.groupby(["housing_median_age", "total_bedrooms"]).mean()
      
Out[16]:
longitude latitude total_rooms population households median_income median_house_value
housing_median_age total_bedrooms
1.0 328.0 -120.93 37.65 2254.0 402.0 112.0 4.2500 189200.0
343.0 -122.00 38.23 2062.0 872.0 268.0 5.2636 191300.0
2.0 18.0 -115.80 33.26 96.0 30.0 16.0 5.3374 47500.0
35.0 -121.93 37.78 227.0 114.0 49.0 3.1591 434700.0
55.0 -117.27 33.93 337.0 115.0 49.0 3.1042 164800.0
... ... ... ... ... ... ... ... ...
52.0 1360.0 -118.35 34.06 3446.0 1768.0 1245.0 2.4722 500001.0
1535.0 -122.41 37.80 3260.0 3260.0 1457.0 0.9000 500001.0
1944.0 -118.25 34.05 2806.0 2232.0 1605.0 0.6775 350000.0
2509.0 -122.41 37.79 6016.0 3436.0 2119.0 2.5166 275000.0
2747.0 -122.41 37.79 5783.0 4518.0 2538.0 1.7240 225000.0

13394 rows × 7 columns

17. Gráficoslink image 60

Pandas ofrece la posibilidad de representar los datos de nuestros DataFrames en gráficos para poder obtener una mejor representación de ello. Para ello hace uso de la librería matplotlib que veremos en el siguiente post

17.1. Gráfica básicalink image 61

Para representar los datos en una gráfica, la manera más fácil es usar el método plot()

serie = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))
serie = serie.cumsum()
      
serie.plot()
      
Out[13]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc5666b9990>
image pandas 1

En el caso de tener un DataFrame, el método plot() representará cada una de las columnas del DataFrame

dataframe = pd.DataFrame(
np.random.randn(1000, 4), index=ts.index, columns=["A", "B", "C", "D"]
)
dataframe = dataframe.cumsum()
      
dataframe.plot()
      
Out[15]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc5663ce610>
image pandas 2

17.2. Diagrama de barras verticaleslink image 62

Hay más métodos de crear gráficos, como el diagrama de barras vertical mediante plot.bar()

dataframe = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
dataframe.plot.bar()
      
image pandas 3

Si queremos apilar las barras, lo indicamos mediante la variable stacked=True

dataframe.plot.bar(stacked=True)
      
Out[20]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc56265c5d0>
image pandas 4

17.3. Diagrama de barras horizontallink image 63

Para crear un diagrama de barras horizontal usamos plot.barh()

dataframe.plot.barh()
      
Out[21]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc56247fa10>
image pandas 5

Si queremos apilar las barras, lo indicamos mediante la variable stacked=True

dataframe.plot.barh(stacked=True)
      
Out[22]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc562d1d2d0>
image pandas 6

17.4. Histogramalink image 64

Para crear un histograma usamos plot.hist()

dataframe = pd.DataFrame(
{
    "a": np.random.randn(1000) + 1,
    "b": np.random.randn(1000),
    "c": np.random.randn(1000) - 1,
}
)
      
dataframe.plot.hist(alpha=0.5)
      
Out[28]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc5650711d0>
image pandas 7

Si queremos apilar las barras, lo indicamos mediante la variable stacked=True

dataframe.plot.hist(alpha=0.5, stacked=True)
      
Out[29]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc5625779d0>
image pandas 8

Si queremos añadir más columnas, es decir, si queremos que el histograma sea más informativo o preciso, lo indicamos mediante la variable bins

dataframe.plot.hist(alpha=0.5, stacked=True, bins=20)
      
Out[30]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc562324990>
image pandas 9

17.5. Diagramas de velaslink image 65

Para crear un diagrama de velas usamos plot.box()

dataframe = pd.DataFrame(np.random.rand(10, 5), columns=["A", "B", "C", "D", "E"])
      
dataframe.plot.box()
      
Out[34]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc56201a410>
image pandas 10

17.6. Gráficos de áreaslink image 66

Para crear un gráfico de áreas usamos plot.area()

dataframe.plot.area()
      
Out[36]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc561e9ca50>
image pandas 11

17.7. Diagrama de dispersiónlink image 67

Para crear un diagrama de dispersión usamos plot.scatter(), donde hay que indicar las variables x y y del diagrama

dataframe.plot.scatter(x='A', y='B')
      
Out[38]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc561e2ff10>
image pandas 12

17.8. Gráfico de contenedor hexágonallink image 68

Para crear un gráfico de contenedor hexagonal usamos plot.hexbin(), donde hay que indicar las variables x y y del diagrama y el tamaño de la malla mediante gridsize

dataframe = pd.DataFrame(np.random.randn(1000, 2), columns=["a", "b"])
dataframe["b"] = dataframe["b"] + np.arange(1000)
      
dataframe.plot.hexbin(x="a", y="b", gridsize=25)
      
Out[40]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fc561cdded0>
image pandas 13

Seguir leyendo

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

¿Alguna vez has hablado con un LLM y te ha respondido algo que suena como si hubiera estado bebiendo café de máquina durante toda la noche? 😂 ¡Eso es lo que llamamos una alucinación en el mundo de los LLMs! Pero no te preocupes, porque no es que tu modelo de lenguaje esté loco (aunque a veces puede parecerlo 🤪). La verdad es que los LLMs pueden ser un poco... creativos cuando se trata de generar texto. Pero gracias a DoLa, un método que utiliza capas de contraste para mejorar la factibilidad de los LLMs, podemos evitar que nuestros modelos de lenguaje se conviertan en escritores de ciencia ficción 😂. En este post, te explicaré cómo funciona DoLa y te mostraré un ejemplo de código para que puedas entender mejor cómo hacer que tus LLMs sean más fiables y menos propensos a inventar historias. ¡Vamos a salvar a nuestros LLMs de la locura y hacer que sean más útiles! 🚀

Últimos posts -->

¿Has visto estos proyectos?

Subtify

Subtify Subtify

Generador de subtítulos para videos en el idioma que desees. Además a cada persona le pone su subtítulo de un color

Ver todos los proyectos -->

¿Quieres aplicar la IA en tu proyecto? Contactame!

¿Quieres mejorar con estos tips?

Últimos tips -->

Usa esto en local

Los espacios de Hugging Face nos permite ejecutar modelos con demos muy sencillas, pero ¿qué pasa si la demo se rompe? O si el usuario la elimina? Por ello he creado contenedores docker con algunos espacios interesantes, para poder usarlos de manera local, pase lo que pase. De hecho, es posible que si pinchas en alún botón de ver proyecto te lleve a un espacio que no funciona.

Ver todos los contenedores -->

¿Quieres aplicar la IA en tu proyecto? Contactame!

¿Quieres entrenar tu modelo con estos datasets?

short-jokes-dataset

Dataset de chistes en inglés

opus100

Dataset con traducciones de inglés a español

netflix_titles

Dataset con películas y series de Netflix

Ver más datasets -->