Extraer datos numéricos de cadenas de texto es una tarea común en la programación Python, particularmente en la limpieza de datos y el web scraping. Este artículo explora varios métodos eficientes y versátiles para lograr esto, atendiendo a diferentes escenarios y niveles de complejidad.
Tabla de Contenidos
- Método 1: Aprovechando las Expresiones Regulares
- Método 2: Utilizando List Comprehension
- Método 3: Combinando
filter
yisdigit()
- Método 4: Expresiones Regulares Avanzadas para Patrones Complejos
- Gestionando Variaciones en los Formatos de Número
- Conclusión
Método 1: Aprovechando las Expresiones Regulares
Las expresiones regulares (regex) ofrecen un enfoque potente y flexible, especialmente para estructuras de cadenas complejas. El módulo re
de Python facilita este proceso.
import re
def extract_numbers_regex(text):
"""Extrae números de una cadena usando expresiones regulares."""
numbers = re.findall(r'-?d+(.d+)?', text) # Coincide con enteros y decimales, incluyendo números negativos
return [float(num) for num in numbers]
text = "Hay -12 manzanas y 3.14 naranjas, y también 12345."
numbers = extract_numbers_regex(text)
print(numbers) # Salida: [-12.0, 3.14, 12345.0]
Esta regex mejorada r'-?d+(.d+)?'
maneja números negativos y decimales eficazmente.
Método 2: Utilizando List Comprehension
List comprehension proporciona una solución concisa y Pythonica, ideal para escenarios más simples donde los números están claramente delimitados.
def extract_numbers_list_comprehension(text):
"""Extrae enteros de una cadena usando list comprehension."""
return [int(c) for c in text if c.isdigit()]
text = "123abc456"
numbers = extract_numbers_list_comprehension(text)
print(numbers) # Salida: [1, 2, 3, 4, 5, 6]
Este método es eficiente para extraer dígitos individuales, pero puede no ser adecuado para números de varios dígitos o números con puntos decimales.
Método 3: Combinando filter
y isdigit()
Este enfoque funcional usa filter()
y isdigit()
para una solución clara y legible, adecuada para casos más simples.
def extract_numbers_filter(text):
"""Extrae enteros de una cadena usando filter e isdigit()."""
numbers = list(filter(str.isdigit, text))
return [int(num) for num in numbers]
text = "1a2b3c4d5"
numbers = extract_numbers_filter(text)
print(numbers) #Salida: [1, 2, 3, 4, 5]
Similar a list comprehension, este método extrae dígitos individuales y no maneja formatos de número más complejos.
Método 4: Expresiones Regulares Avanzadas para Patrones Complejos
Las expresiones regulares realmente brillan al manejar patrones intrincados, como números en notación científica o con separadores de miles.
import re
def extract_numbers_complex(text):
"""Extrae números (incluyendo notación científica) de una cadena usando regex."""
numbers = re.findall(r'-?d+(?:,d{3})*(?:.d+)?(?:[eE][+-]?d+)?', text)
return [float(num.replace(',', '')) for num in numbers]
text = "El precio es $1,234.56 y la cantidad es 1.23e-5. Otro precio es 100,000"
numbers = extract_numbers_complex(text)
print(numbers) # Salida: ['1234.56', '1.23e-5', '100000']
Esta regex maneja comas como separadores de miles y notación científica. El replace(',', '')
elimina las comas antes de la conversión a float.
Gestionando Variaciones en los Formatos de Número
Para adaptarse a varios formatos, considere estos puntos:
- Números negativos: Incluya
-?
al principio de su patrón regex (ej.,r'-?d+'
). - Notación científica: Añada
(?:[eE][+-]?d+)?
para manejar exponentes (como se muestra en el Método 4). - Separadores de miles: Use
(?:,d{3})*
para coincidir con separadores de miles opcionales (como se muestra en el Método 4). - Símbolos monetarios: Preprocese su cadena para eliminar los símbolos monetarios antes de la extracción, o use una regex más compleja.
Conclusión
El método óptimo depende de la complejidad de sus cadenas de entrada y la precisión deseada. Para casos simples, list comprehension o filter
podrían ser suficientes. Sin embargo, para la robustez y el manejo de diversos formatos de número, las expresiones regulares son invaluables.