Comprensión de listas para el procesamiento de elementos

Beginner

This tutorial is from open-source community. Access the source code

Introducción

Una tarea común es procesar elementos de una lista. En esta sección se presentan las comprensiones de lista, una herramienta poderosa para hacer precisamente eso.

Este es un Guided Lab, que proporciona instrucciones paso a paso para ayudarte a aprender y practicar. Sigue las instrucciones cuidadosamente para completar cada paso y obtener experiencia práctica. Los datos históricos muestran que este es un laboratorio de nivel principiante con una tasa de finalización del 91%. Ha recibido una tasa de reseñas positivas del 100% por parte de los estudiantes.

Creando nuevas listas

Una comprensión de lista crea una nueva lista aplicando una operación a cada elemento de una secuencia.

>>> a = [1, 2, 3, 4, 5]
>>> b = [2*x for x in a ]
>>> b
[2, 4, 6, 8, 10]
>>>

Otro ejemplo:

>>> names = ['Elwood', 'Jake']
>>> a = [name.lower() for name in names]
>>> a
['elwood', 'jake']
>>>

La sintaxis general es: [ <expresión> for <nombre_variable> in <secuencia> ].

Filtrado

También puedes filtrar durante la comprensión de lista.

>>> a = [1, -5, 4, 2, -2, 10]
>>> b = [2*x for x in a if x > 0 ]
>>> b
[2, 8, 4, 20]
>>>

Casos de uso

Las comprensiones de lista son muy útiles. Por ejemplo, puedes recopilar los valores de un campo específico de un diccionario:

stocknames = [s['name'] for s in stocks]

Puedes realizar consultas similares a las de una base de datos en secuencias.

a = [s for s in stocks if s['price'] > 100 and s['shares'] > 50 ]

También puedes combinar una comprensión de lista con una reducción de secuencia:

cost = sum([s['shares']*s['price'] for s in stocks])

Sintaxis general

[ <expresión> for <nombre_variable> in <secuencia> if <condición>]

Qué significa:

result = []
for nombre_variable in secuencia:
    if condición:
        result.append(expresión)

Digresión histórica

Las comprensiones de lista provienen de las matemáticas (notación de construcción de conjuntos).

a = [ x * x for x in s if x > 0 ] ## Python

a = { x^2 | x ∈ s, x > 0 }         ## Matemáticas

También está implementada en varios otros lenguajes. Sin embargo, la mayoría de los programadores probablemente no están pensando en su clase de matemáticas. Entonces, está bien verla como un atajo de lista genial.

Ejercicio 2.19: Comprensiones de lista

Prueba algunas comprensiones de lista simples solo para familiarizarte con la sintaxis.

>>> nums = [1,2,3,4]
>>> squares = [ x * x for x in nums ]
>>> squares
[1, 4, 9, 16]
>>> twice = [ 2 * x for x in nums if x > 2 ]
>>> twice
[6, 8]
>>>

Observa cómo las comprensiones de lista están creando una nueva lista con los datos adecuadamente transformados o filtrados.

Ejercicio 2.20: Reducciones de secuencia

Calcula el costo total de la cartera utilizando una sola instrucción de Python.

>>> portfolio = read_portfolio('portfolio.csv')
>>> cost = sum([ s['shares'] * s['price'] for s in portfolio ])
>>> cost
44671.15
>>>

Una vez que hayas hecho eso, muestra cómo puedes calcular el valor actual de la cartera utilizando una sola instrucción.

>>> value = sum([ s['shares'] * prices[s['name']] for s in portfolio ])
>>> value
28686.1
>>>

Ambas operaciones anteriores son un ejemplo de map-reduce. La comprensión de lista está aplicando una operación a través de la lista.

>>> [ s['shares'] * s['price'] for s in portfolio ]
[3220.0000000000005, 4555.0, 12516.0, 10246.0, 3835.1499999999996, 3254.9999999999995, 7044.0]
>>>

La función sum() luego está realizando una reducción en el resultado:

>>> sum(_)
44671.15
>>>

Con este conocimiento, ya estás listo para lanzar una empresa de startups de big data.

Ejercicio 2.21: Consultas de datos

Prueba los siguientes ejemplos de diversas consultas de datos.

Primero, una lista de todas las posesiones de la cartera con más de 100 acciones.

>>> more100 = [ s for s in portfolio if s['shares'] > 100 ]
>>> more100
[{'price': 83.44, 'name': 'CAT','shares': 150}, {'price': 51.23, 'name': 'MSFT','shares': 200}]
>>>

Todas las posesiones de la cartera de las acciones de MSFT e IBM.

>>> msftibm = [ s for s in portfolio if s['name'] in {'MSFT','IBM'} ]
>>> msftibm
[{'price': 91.1, 'name': 'IBM','shares': 50}, {'price': 51.23, 'name': 'MSFT','shares': 200},
  {'price': 65.1, 'name': 'MSFT','shares': 50}, {'price': 70.44, 'name': 'IBM','shares': 100}]
>>>

Una lista de todas las posesiones de la cartera que cuestan más de $10000.

>>> cost10k = [ s for s in portfolio if s['shares'] * s['price'] > 10000 ]
>>> cost10k
[{'price': 83.44, 'name': 'CAT','shares': 150}, {'price': 51.23, 'name': 'MSFT','shares': 200}]
>>>

Ejercicio 2.22: Extracción de datos

Muestra cómo podrías construir una lista de tuplas (nombre, acciones) donde nombre y acciones se tomen de portfolio.

>>> name_shares =[ (s['name'], s['shares']) for s in portfolio ]
>>> name_shares
[('AA', 100), ('IBM', 50), ('CAT', 150), ('MSFT', 200), ('GE', 95), ('MSFT', 50), ('IBM', 100)]
>>>

Si cambias los corchetes ([, ]) por llaves ({, }), obtienes algo conocido como una comprensión de conjunto. Esto te da valores únicos o distintos.

Por ejemplo, esto determina el conjunto de nombres de acciones únicos que aparecen en portfolio:

>>> names = { s['name'] for s in portfolio }
>>> names
{ 'AA', 'GE', 'IBM', 'MSFT', 'CAT' }
>>>

Si especificas pares clave:valor, puedes construir un diccionario. Por ejemplo, crea un diccionario que asocie el nombre de una acción con el número total de acciones poseídas.

>>> holdings = { name: 0 for name in names }
>>> holdings
{'AA': 0, 'GE': 0, 'IBM': 0, 'MSFT': 0, 'CAT': 0}
>>>

Esta última característica se conoce como una comprensión de diccionario. Hagamos una tabla:

>>> for s in portfolio:
        holdings[s['name']] += s['shares']

>>> holdings
{ 'AA': 100, 'GE': 95, 'IBM': 150, 'MSFT':250, 'CAT': 150 }
>>>

Prueba este ejemplo que filtra el diccionario prices solo a aquellos nombres que aparecen en la cartera:

>>> portfolio_prices = { name: prices[name] for name in names }
>>> portfolio_prices
{'AA': 9.22, 'GE': 13.48, 'IBM': 106.28, 'MSFT': 20.89, 'CAT': 35.46}
>>>

Ejercicio 2.23: Extracción de datos de archivos CSV

Saberse utilizar diversas combinaciones de comprensiones de lista, conjunto y diccionario puede ser útil en diversas formas de procesamiento de datos. Aquí hay un ejemplo que muestra cómo extraer columnas seleccionadas de un archivo CSV.

Primero, lee una fila de información de encabezado de un archivo CSV:

>>> import csv
>>> f = open('portfoliodate.csv')
>>> rows = csv.reader(f)
>>> headers = next(rows)
>>> headers
['name', 'date', 'time','shares', 'price']
>>>

Luego, define una variable que liste las columnas en las que realmente te interesa:

>>> select = ['name','shares', 'price']
>>>

Ahora, localiza los índices de las columnas anteriores en el archivo CSV de origen:

>>> indices = [ headers.index(colname) for colname in select ]
>>> indices
[0, 3, 4]
>>>

Finalmente, lee una fila de datos y conviértela en un diccionario utilizando una comprensión de diccionario:

>>> row = next(rows)
>>> record = { colname: row[index] for colname, index in zip(select, indices) }   ## dict-comprehension
>>> record
{'price': '32.20', 'name': 'AA','shares': '100'}
>>>

Si te sientes cómodo con lo que acaba de suceder, lee el resto del archivo:

>>> portfolio = [ { colname: row[index] for colname, index in zip(select, indices) } for row in rows ]
>>> portfolio
[{'price': '91.10', 'name': 'IBM','shares': '50'}, {'price': '83.44', 'name': 'CAT','shares': '150'},
  {'price': '51.23', 'name': 'MSFT','shares': '200'}, {'price': '40.37', 'name': 'GE','shares': '95'},
  {'price': '65.10', 'name': 'MSFT','shares': '50'}, {'price': '70.44', 'name': 'IBM','shares': '100'}]
>>>

Oh, mira, acabas de reducir gran parte de la función read_portfolio() a una sola instrucción.

Comentario

Las comprensiones de lista se utilizan comúnmente en Python como un medio eficiente para transformar, filtrar o recopilar datos. Debido a la sintaxis, no quieres exagerar, trata de mantener cada comprensión de lista lo más simple posible. Está bien dividir las cosas en pasos múltiples. Por ejemplo, no está claro que quieres sorprender a tus compañeros de trabajo con el último ejemplo sin previo aviso.

Dicho esto, saber manipular rápidamente los datos es una habilidad que es increíblemente útil. Hay numerosas situaciones en las que es posible que tengas que resolver algún tipo de problema único que involucre importaciones, exportaciones, extracciones de datos, etc. Convertirse en un maestro guru de las comprensiones de lista puede reducir sustancialmente el tiempo invertido en idear una solución. Además, no olvides el módulo collections.

Resumen

¡Felicitaciones! Has completado el laboratorio de Comprensiones de Lista. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.