pandas

Pandas

Tutorial Pandas: Series

Pandas Series: Aprende desde la creación básica hasta la manipulación y optimización avanzada de datos en Series con ejemplos prácticos.

¿Qué son las Series en Pandas y cómo se crean?

Las Series en Pandas son una de las estructuras de datos fundamentales que ofrece esta biblioteca. Una Serie es esencialmente una columna de datos que tiene un índice asociado, lo que permite un acceso más eficiente y flexible a los datos. 

Cada Serie en Pandas es un objeto unidimensional que puede contener cualquier tipo de datos, como enteros, cadenas, flotantes o incluso otros objetos.

Para crear una Serie en Pandas, se puede utilizar el constructor pd.Series(). Este constructor permite crear una Serie a partir de varias estructuras de datos como listas, diccionarios, arrays de NumPy o incluso una constante.

Creación de Series a partir de una lista

import pandas as pd

data = [10, 20, 30, 40, 50]
serie = pd.Series(data)
print(serie)

El código anterior generará la siguiente salida:

0    10
1    20
2    30
3    40
4    50
dtype: int64

Creación de Series a partir de un diccionario

import pandas as pd

data = {'a': 1, 'b': 2, 'c': 3}
serie = pd.Series(data)
print(serie)

La salida será:

a    1
b    2
c    3
dtype: int64

Creación de Series a partir de un array de NumPy

import pandas as pd
import numpy as np

data = np.array([1, 2, 3, 4, 5])
serie = pd.Series(data)
print(serie)

La salida será:

0    1
1    2
2    3
3    4
4    5
dtype: int64

Creación de Series a partir de una constante

import pandas as pd

serie = pd.Series(5, index=['a', 'b', 'c', 'd'])
print(serie)

La salida será:

a    5
b    5
c    5
d    5
dtype: int64

Especificación de un índice personalizado

Al crear una Serie, se puede especificar un índice personalizado. Esto es útil para asignar etiquetas significativas a los datos.

import pandas as pd

data = [10, 20, 30]
index = ['x', 'y', 'z']
serie = pd.Series(data, index=index)
print(serie)

La salida será:

x    10
y    20
z    30
dtype: int64

Series con datos de diferentes tipos

Las Series en Pandas pueden contener datos de diferentes tipos. Si los datos tienen tipos mixtos, la Serie será de tipo object.

import pandas as pd

data = [1, 'a', 3.5]
serie = pd.Series(data)
print(serie)

La salida será:

0      1
1      a
2    3.5
dtype: object

En resumen, las Series en Pandas son una estructura de datos flexible y eficiente para manejar datos unidimensionales con un índice asociado. La creación de Series puede realizarse a partir de diversas estructuras de datos, proporcionando una gran versatilidad en su uso.

Atributos de las Series

Las Series en Pandas cuentan con varios atributos que proporcionan información y características esenciales sobre los datos que contienen. Estos atributos son extremadamente útiles para entender y manipular las Series de manera eficiente.

  • index: Devuelve el índice (etiquetas) de la Serie. Este atributo es de tipo pd.Index.
import pandas as pd

serie = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
print(serie.index)

Salida:

Index(['a', 'b', 'c'], dtype='object')
  • values: Devuelve los valores de la Serie como un array de NumPy. Esto es útil para operaciones de bajo nivel o cuando se requiere un acceso más directo a los datos. Nota: Aunque el atributo values sigue disponible, se recomienda utilizar el método to_numpy() para obtener los datos como un array de NumPy, ya que es más flexible y seguro en diversas situaciones.
print(serie.values)

Salida:

[10 20 30]
  • name: Permite asignar o devolver el nombre de la Serie. Este atributo es útil cuando se trabaja con DataFrames y se desean identificar las Series por su nombre.
serie.name = 'mi_serie'
print(serie.name)

Salida:

mi_serie
  • dtype: Devuelve el tipo de dato de los elementos en la Serie. Este atributo es crucial para entender el tipo de datos con los que se está trabajando y es útil para realizar conversiones de tipo si es necesario.
print(serie.dtype)

Salida:

int64
  • size: Devuelve el número de elementos en la Serie. Este atributo es útil para obtener rápidamente la longitud de la Serie.
print(serie.size)

Salida:

3
  • shape: Devuelve una tupla que indica la forma de la Serie. Aunque para Series siempre será (n,) donde n es el número de elementos, este atributo es coherente con otras estructuras de datos como DataFrames.
print(serie.shape)

Salida:

(3,)
  • empty: Devuelve un booleano que indica si la Serie está vacía o no. Este atributo es útil para validaciones rápidas.
print(serie.empty)

Salida:

False
  • nbytes: Devuelve el número de bytes que ocupan los datos de la Serie en memoria. Este atributo es útil para análisis de rendimiento y optimización de memoria.
print(serie.nbytes)

Salida:

24
  • hasnans: Devuelve un booleano que indica si la Serie contiene valores NaN. Este atributo es útil para la limpieza de datos y validaciones.
serie_with_nan = pd.Series([1, 2, None])
print(serie_with_nan.hasnans)

Salida:

True
  • is_unique: Devuelve un booleano que indica si todos los valores en la Serie son únicos. Este atributo es útil para validar la unicidad de datos en ciertas operaciones.
print(serie.is_unique)

Salida:

True

Estos atributos proporcionan una manera eficiente de inspeccionar y analizar Series de Pandas, permitiendo a los ingenieros de software tomar decisiones informadas sobre cómo manipular y transformar los datos.

Acceso a datos de Series con iloc y loc

En Pandas, iloc y loc son dos métodos primarios para acceder a los datos en una Serie. Ambos permiten la selección de datos, pero con diferentes enfoques: iloc se basa en la posición (índices numéricos) y loc se basa en las etiquetas del índice.

Acceso con iloc

iloc permite la selección de datos basada en la posición numérica del índice. Este método es útil cuando se conoce la posición exacta de los elementos que se desean acceder.

import pandas as pd

serie = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])

# Acceso al primer elemento
print(serie.iloc[0])

Salida:

10

Se pueden seleccionar múltiples elementos utilizando listas de índices o slices.

# Selección de múltiples elementos
print(serie.iloc[[0, 2, 3]])

# Selección de un rango de elementos
print(serie.iloc[1:4])

Salida:

a    10
c    30
d    40
dtype: int64

b    20
c    30
d    40
dtype: int64

Acceso con loc

loc permite la selección de datos basada en las etiquetas del índice. Este método es más intuitivo cuando se trabaja con índices significativos.

# Acceso al elemento con etiqueta 'a'
print(serie.loc['a'])

Salida:

10

Al igual que con iloc, se pueden seleccionar múltiples elementos utilizando listas de etiquetas o slices basados en etiquetas.

# Selección de múltiples elementos
print(serie.loc[['a', 'c', 'd']])

# Selección de un rango de elementos
print(serie.loc['b':'d'])

Salida:

a    10
c    30
d    40
dtype: int64

b    20
c    30
d    40
dtype: int64

Diferencias clave entre iloc y loc

  • iloc siempre se basa en la posición numérica del índice, independientemente de las etiquetas.
  • loc siempre se basa en las etiquetas del índice, lo que permite una selección más semántica y contextual.
  • iloc puede generar errores si se intenta acceder a una posición fuera del rango del índice.
  • loc puede generar errores si se intenta acceder a una etiqueta que no existe en el índice.

Uso avanzado de iloc y loc

Ambos métodos permiten el uso de condiciones booleanas para la selección de datos.

# Selección de elementos mayores a 20 usando iloc
print(serie[serie.iloc > 20])

# Selección de elementos mayores a 20 usando loc
print(serie[serie.loc > 20])

Salida:

c    30
d    40
e    50
dtype: int64

c    30
d    40
e    50
dtype: int64

Además, es posible modificar los valores de una Serie utilizando iloc y loc.

# Modificación de un elemento usando iloc
serie.iloc[0] = 100
print(serie)

# Modificación de un elemento usando loc
serie.loc['b'] = 200
print(serie)

Salida:

a    100
b     20
c     30
d     40
e     50
dtype: int64

a    100
b    200
c     30
d     40
e     50
dtype: int64

Estas capacidades de acceso y manipulación proporcionan una gran flexibilidad y control al trabajar con datos en Series de Pandas.

Operaciones y manipulación sobre Series

Las Series en Pandas ofrecen una amplia gama de operaciones y técnicas de manipulación que permiten transformar y analizar los datos de manera eficiente. A continuación, se describen algunas de las operaciones más comunes y avanzadas que se pueden realizar sobre Series.

Operaciones aritméticas

Las Series permiten realizar operaciones aritméticas básicas como suma, resta, multiplicación y división. Estas operaciones se aplican elemento por elemento y pueden realizarse con otras Series, arrays de NumPy o constantes.

import pandas as pd

serie1 = pd.Series([1, 2, 3, 4])
serie2 = pd.Series([10, 20, 30, 40])

# Suma
print(serie1 + serie2)

# Resta
print(serie1 - serie2)

# Multiplicación
print(serie1 * serie2)

# División
print(serie1 / serie2)

Salida:

0    11
1    22
2    33
3    44
dtype: int64

0    -9
1   -18
2   -27
3   -36
dtype: int64

0     10
1     40
2     90
3    160
dtype: int64

0    0.1
1    0.1
2    0.1
3    0.1
dtype: float64

Aplicación de funciones: apply y map

Pandas permite aplicar funciones a los elementos de una Serie utilizando apply y map. Estas funciones son útiles para realizar transformaciones complejas y personalizadas.

# Usando apply para aplicar una función lambda
print(serie1.apply(lambda x: x**2))

# Usando map para aplicar una función predefinida
print(serie1.map(str))

Salida:

0     1
1     4
2     9
3    16
dtype: int64

0    1
1    2
2    3
3    4
dtype: object

Ordenación y clasificación

Las Series pueden ordenarse utilizando el método sort_values y clasificarse con rank.

serie = pd.Series([3, 1, 4, 1, 5, 9, 2])

# Ordenar por valores
print(serie.sort_values())

# Clasificar valores
print(serie.rank())

Salida:

1    1
3    1
6    2
0    3
2    4
4    5
5    9
dtype: int64

0    4.0
1    1.5
2    5.0
3    1.5
4    6.0
5    7.0
6    3.0
dtype: float64

Filtrado y selección condicional

Las Series permiten filtrar elementos basados en condiciones, lo que es útil para la limpieza y análisis de datos.

# Filtrar elementos mayores a 2
print(serie[serie > 2])

# Filtrar elementos que son pares
print(serie[serie % 2 == 0])

Salida:

0    3
2    4
4    5
5    9
dtype: int64

2    4
6    2
dtype: int64

Manejo de valores nulos

Pandas proporciona métodos para manejar valores nulos en las Series, como isna, fillna y dropna.

serie_with_nan = pd.Series([1, 2, None, 4, None])

# Detectar valores nulos
print(serie_with_nan.isna())

# Rellenar valores nulos con un valor específico
print(serie_with_nan.fillna(0))

# Eliminar valores nulos
print(serie_with_nan.dropna())

Salida:

0    False
1    False
2     True
3    False
4     True
dtype: bool

0    1.0
1    2.0
2    0.0
3    4.0
4    0.0
dtype: float64

0    1.0
1    2.0
3    4.0
dtype: float64

Operaciones de alineación y combinación

Las Series en Pandas se alinean automáticamente según sus índices cuando se realizan operaciones entre ellas. Esto permite combinar datos de diferentes fuentes de manera coherente.

serie1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
serie2 = pd.Series([4, 5, 6], index=['b', 'c', 'd'])

# Suma de Series con alineación automática
print(serie1 + serie2)

Salida:

a    NaN
b    6.0
c    8.0
d    NaN
dtype: float64

Reindexación

El método reindex permite cambiar el índice de una Serie, añadiendo o eliminando etiquetas según sea necesario.

serie = pd.Series([1, 2, 3], index=['a', 'b', 'c'])

# Reindexar la Serie
reindexed_serie = serie.reindex(['a', 'b', 'd'])
print(reindexed_serie)

Salida:

a    1.0
b    2.0
d    NaN
dtype: float64

Estas operaciones y técnicas de manipulación permiten una gran flexibilidad al trabajar con Series en Pandas, facilitando el análisis y la transformación de datos de manera eficiente y efectiva.

Optimización y rendimiento de Series

La optimización y el rendimiento en el manejo de Series en Pandas son aspectos cruciales para trabajar con grandes volúmenes de datos de manera eficiente. A continuación, se presentan técnicas y prácticas recomendadas para mejorar el rendimiento al trabajar con Series.

Primero, es importante entender que Pandas está construido sobre NumPy, lo que significa que muchas de las optimizaciones de rendimiento se derivan del uso eficiente de arrays de NumPy. 

Las Series en Pandas están diseñadas para ser rápidas y eficientes, pero hay varias estrategias adicionales que se pueden emplear para mejorar aún más el rendimiento.

Tipos de datos y memoria

El tipo de datos de una Serie puede tener un impacto significativo en el rendimiento y el uso de memoria. Es recomendable utilizar tipos de datos más eficientes siempre que sea posible.

import pandas as pd

# Crear una Serie con tipo de dato int64
serie = pd.Series([1, 2, 3, 4, 5], dtype='int64')
print(serie.memory_usage(deep=True))

# Convertir la Serie a tipo int32
serie = serie.astype('int32')
print(serie.memory_usage(deep=True))

El uso de tipos de datos más pequeños puede reducir considerablemente el uso de memoria, lo que es crucial cuando se trabaja con grandes datasets.

Uso de operaciones vectorizadas

Las operaciones vectorizadas en Pandas y NumPy son más rápidas que los bucles explícitos de Python. Siempre que sea posible, utilice operaciones vectorizadas para manipular Series.

import pandas as pd
import numpy as np

# Crear un generador aleatorio
rng = np.random.default_rng(seed=42)

# Generar la serie utilizando el nuevo generador aleatorio
serie = pd.Series(rng.random(1000000))

# Operación vectorizada
result = serie * 2

Evite el uso de bucles for para realizar operaciones en Series, ya que son significativamente más lentos.

Evitar la copia innecesaria de datos

Algunas operaciones en Pandas pueden resultar en la copia de datos, lo que puede ser costoso en términos de memoria y tiempo. Utilice las opciones inplace=True cuando estén disponibles para modificar objetos en el lugar y evitar la creación de copias.

# Modificar una Serie en el lugar para evitar la copia
serie = pd.Series([1, 2, 3, 4, 5])
serie.drop(0, inplace=True)

Uso eficiente de apply y map

Aunque apply y map son útiles para aplicar funciones a una Serie, pueden ser lentos para grandes volúmenes de datos. Siempre que sea posible, utilice funciones vectorizadas en lugar de apply o map.

import pandas as pd
import numpy as np

# Crear un generador aleatorio
rng = np.random.default_rng(seed=42)

# Generar la serie utilizando el nuevo generador aleatorio
serie = pd.Series(rng.random(1000000))

# Uso de una función vectorizada en lugar de apply
result = np.sqrt(serie)

Filtrado y selección condicional

El filtrado y la selección condicional pueden ser optimizados utilizando operaciones vectorizadas y evitando la creación de copias innecesarias de datos.

import pandas as pd
import numpy as np

# Crear un generador aleatorio
rng = np.random.default_rng(seed=42)

# Generar la serie utilizando el nuevo generador aleatorio
serie = pd.Series(rng.random(1000000))

# Filtrado eficiente de una Serie
filtered_serie = serie[serie > 0.5]

Uso de pd.eval y query

Para operaciones complejas, pd.eval y query pueden mejorar significativamente el rendimiento al compilar expresiones a código nativo.

import pandas as pd
import numpy as np

# Crear un generador aleatorio
rng = np.random.default_rng(seed=42)

# Generar la serie utilizando el nuevo generador aleatorio
serie = pd.Series(rng.random(1000000))

# Uso de pd.eval para operaciones complejas
result = pd.eval('serie * 2 + 1')

Manejo de valores nulos

El manejo de valores nulos puede ser costoso en términos de rendimiento. Utilice métodos eficientes como fillna y dropna para tratar con valores nulos.

# Rellenar valores nulos de manera eficiente
serie = pd.Series([1, 2, None, 4, 5])
serie.fillna(0, inplace=True)

Uso de índices eficientes

El uso de índices eficientes puede mejorar el rendimiento de las operaciones de búsqueda y selección. Asegúrese de que los índices estén correctamente configurados y optimizados.

# Configurar un índice eficiente
serie = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])
print(serie.loc['c'])
Certifícate en Pandas con CertiDevs PLUS

Ejercicios de esta lección Series

Evalúa tus conocimientos de esta lección Series con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de Pandas

Accede a todas las lecciones de Pandas y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Certificados de superación de Pandas

Supera todos los ejercicios de programación del curso de Pandas y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  • Entender qué es una Serie en Pandas y sus características fundamentales.

  • Crear Series a partir de listas, diccionarios, arrays de NumPy y constantes.

  • Manipular Series utilizando índices personalizados.

  • Acceder a los datos de Series con iloc y loc.

  • Realizar operaciones y manipulaciones avanzadas sobre Series.

  • Optimizar el rendimiento al trabajar con Series.