Iteración y Comprensiones en Python
Iteración y Comprensiones en Python
Se te proporciona la lista de cadenas flash. Practicarás la iteración en la lista utilizando un bucle for.
También crearás un iterador para la lista y accederás a los valores desde el iterador.
Instrucciones
Crea un bucle for para aplicarlo a flash e imprimir los valores de la lista. Utiliza person como variable
de bucle.
Crea un iterador para la lista flash y asigna el resultado a superhero.
Imprime cada uno de los elementos de superhero utilizando next() 4 veces.
Puedes utilizar range() en un bucle for como si fuera una lista en la que iterar:
for i in range(5):
print(i)
Recuerda que range() no crea realmente la lista, sino un objeto range con un iterador que produce los
valores hasta que alcanza el límite (en el ejemplo, hasta el valor 4). Si range() ha creado la lista real,
llamarla con un valor de 10^100 puede no funcionar, sobre todo porque un número tan grande como
ese puede sobrepasar la memoria de un ordenador normal. El valor 10^100 es en realidad lo que se
llama un gúgol, que es un 1 seguido de cien ceros. ¡Es un número enorme!
Tu tarea para este ejercicio es demostrar que llamar a range() con 10^100 no precrea realmente la
lista.
Instrucciones
También hay funciones que toman iteradores e iterables como argumentos. Por ejemplo, las
funciones list() y sum() devuelven una lista y la suma de elementos, respectivamente.
Instrucciones
Crea un objeto range que produzca los valores de 10 a 20 utilizando range(). Asigna el resultado
a values.
Utiliza la función list() para crear una lista de valores a partir del objeto range values. Asigna el
resultado a values_list.
Utiliza la función sum() para obtener la suma de los valores de 10 a 20 del objeto range values. Asigna
el resultado a values_sum.
# Print values_list
print(values_list)
# Print values_sum
print(values_sum)
out:
"range(10, 21)
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 165"
Uso de enumerate
Realmente le estás cogiendo el tranquillo al uso de los iteradores, ¡gran trabajo!
Acabas de recibir varias ideas nuevas sobre los iteradores en el último vídeo, y una de ellas es la
función enumerate(). Recuerda que enumerate() devuelve un objeto enumerate que produce una
secuencia de tuplas, y cada una de las tuplas es un par índice-valor.
Instrucciones
Crea una lista de tuplas a partir de mutants y asigna el resultado a mutant_list. Asegúrate de generar
las tuplas utilizando enumerate() y de convertir su resultado en una lista utilizando list().
Completa el primer bucle for descomprimiendo las tuplas generadas llamando
a enumerate() en mutants. Utiliza para el índice y index1 para el valor al descomprimir la tupla.
Completa el segundo bucle for de forma similar al primero, pero esta vez cambia el índice inicial para
que comience en 1 pasándolo como argumento al parámetro start de enumerate(). Utiliza para el
índice y index2 para el valor al descomprimir la tupla.
Instrucciones
Utilizando zip() con list(), crea una lista de tuplas a partir de las listas mutants, aliases y powers (en
ese orden) y asigna el resultado a mutant_data.
Utilizando zip(), crea un objeto zip llamado mutant_zip a partir de las listas mutants, aliases y powers.
Completa el bucle for descomprimiendo el objeto zip que has creado e imprimiendo los valores de
tupla. Utiliza value1, value2 y value3 para los valores de mutants, aliases y powers en ese orden.
out:
"[('charles xavier', 'prof x', 'telepathy'),
('bobby drake', 'iceman', 'thermokinesis'),
('kurt wagner', 'nightcrawler', 'teleportation'),
('max eisenhardt', 'magneto', 'magnetokinesis'),
('kitty pryde', 'shadowcat', 'intangibility')]
<zip object at 0x7fdc127397c0>
En resumen, esta solución utiliza zip() para combinar las listas en tuplas, primero creando una lista
de tuplas y luego iterando sobre un objeto zip para imprimir cada conjunto de datos. Esto cumple con
los requisitos del ejercicio de manera efectiva.
Uso de * y zip para "descomprimir"
Sabes cómo utilizar zip() y cómo imprimir valores de un objeto zip. ¡Excelente!
Juguemos un poco más con zip(). No existe una función de descompresión para hacer lo contrario de
lo que hace zip(). Sin embargo, podemos invertir el resultado de zip utilizando zip() con un poco de
ayuda de *. * descomprime un iterable como una lista o una tupla en argumentos posicionales en una
llamada a función.
En este ejercicio, utilizarás * en una llamada a zip() para descomprimir las tuplas producidas por zip().
Se han precargado dos tuplas de cadenas, mutants y powers.
Instrucciones
Crea un objeto zip utilizando zip() en mutants y powers en ese orden. Asigna el resultado a .
Imprime las tuplas de z1 descomprimiéndolas en argumentos posicionales con el operador * en una
llamada a print().
Como la llamada anterior a print() habría agotado los elementos de z1, vuelve a crear el objeto zip que
definiste anteriormente y asigna de nuevo el resultado a z1.
"Descomprime" las tuplas de z1 descomprimiéndolas en argumentos posicionales con el
operador * en una llamada a zip(). Asigna los resultados a result1 y result2 en ese orden.
Las últimas declaraciones print() imprimen la salida de
comparar result1 con mutants y result2 con powers. Haz clic en Submit Answer para ver
si result1 y result2 descomprimidos son equivalentes a mutants y powers, respectivamente.
out:
"('charles xavier', 'telepathy') ('bobby drake', 'thermokinesis') ('kurt wagner', 'teleportation') ('max
eisenhardt', 'magnetokinesis') ('kitty pryde', 'intangibility')
True
True"
Claro, vamos a desglosar la solución paso a paso para entender cómo resuelve el ejercicio:
1. Creación del objeto zip:
z1 = zip(mutants, powers)
Aquí estamos creando un objeto zip llamado z1 que combina los elementos de las
tuplas mutants y powers. Cada elemento de z1 es una tupla que contiene un elemento de mutants y
el elemento correspondiente de powers.
2. Impresión de las tuplas en z1:
print(*z1)
Utilizamos el operador * para desempaquetar el objeto zip z1 en argumentos posicionales para la
función print(). Esto imprime cada tupla contenida en z1. Sin embargo, al hacer esto, agotamos el
iterador z1, lo que significa que ya no podemos usarlo nuevamente sin recrearlo.
3. Recreación del objeto zip:
z1 = zip(mutants, powers)
Dado que el objeto zip original se agotó al imprimirlo, lo recreamos para poder usarlo nuevamente en
los siguientes pasos.
4. "Desempaquetado" de las tuplas en z1:
result1, result2 = zip(*z1)
Aquí, utilizamos el operador * nuevamente para desempaquetar las tuplas en z1 y pasarlas como
argumentos posicionales a la función zip(). Esto efectivamente "desempaqueta" el objeto zip original
en dos tuplas separadas: result1 y result2. result1 contendrá todos los primeros elementos de las
tuplas originales en z1 (es decir, los elementos de mutants), y result2 contendrá todos los segundos
elementos (es decir, los elementos de powers).
5. Comparación de los resultados desempaquetados:
print(result1 == mutants)
print(result2 == powers)
Finalmente, comparamos result1 con mutants y result2 con powers para verificar si el
desempaquetado fue correcto. Si ambas
Procesamiento de grandes cantidades de datos de Twitter
A veces, los datos que tenemos que procesar alcanzan un tamaño excesivo para la memoria de un
ordenador. Este es un problema común al que se enfrentan los científicos de datos. Una solución a
esto es procesar toda una fuente de datos fragmento a fragmento, en lugar de hacerlo de una sola
vez. En este ejercicio, harás precisamente eso. Procesarás un gran archivo .csv de datos de Twitter
igual que procesaste '[Link]' en los ejercicios de ¡Juntarlo todo! del curso precuela, pero, ahora,
trabajando en fragmentos de 10 entradas cada vez. Si te interesa aprender cómo acceder a datos de
Twitter para poder trabajar con ellos en tu propio sistema, consulta la Parte 2 del curso de DataCamp
sobre importación de datos en Python. El paquete pandas se ha importado como pd y el
archivo '[Link]' está en tu directorio actual para que lo utilices. Ten en cuenta que se trata de
datos reales de Twitter, por lo que siempre existe el riesgo de que encuentres lenguaje soez u otro
contenido ofensivo (en este ejercicio y en los siguientes que también utilicen datos reales de Twitter).
Instrucciones
Inicializa el diccionario vacío counts_dict para almacenar los resultados del procesamiento de los
datos de Twitter. Itera sobre el archivo '[Link]' utilizando un bucle for. Utiliza la variable de
bucle chunk e itera sobre la llamada a pd.read_csv() con un chunksize de 10. En el bucle interior, itera
sobre la columna 'lang' de chunk utilizando un bucle for. Utiliza la variable de bucle entry.
out:
{'en': 97, 'et': 1, 'und': 2}
Esta solución cumple con los requisitos del ejercicio al inicializar un diccionario vacío, iterar sobre el
archivo en fragmentos, y contar la frecuencia de cada idioma en la columna 'lang'.
Extracción de información en grandes cantidades de datos de Twitter
Buen trabajo fragmentando ese archivo en el ejercicio anterior. Ahora sabes cómo enfrentarte a
situaciones en las que tienes que procesar un archivo muy grande, y esa es una competencia muy
útil. Es bueno saber cómo procesar un archivo en fragmentos más pequeños y manejables, pero
puede llegar a ser muy tedioso tener que escribir y volver a escribir cada vez el mismo código para la
misma tarea. En este ejercicio, harás tu código más reutilizable poniendo tu trabajo del último
ejercicio en una definición de función. El paquete pandas se ha importado como pd y el
archivo '[Link]' está en tu directorio actual para que lo utilices.
Instrucciones
Define la función count_entries(), que tiene 3 parámetros. El primer parámetro es csv_file para el
nombre de archivo, el segundo es c_size para el tamaño de fragmento y el último es colname para el
nombre de columna.
Itera sobre el archivo en el archivo csv_file utilizando un bucle for. Utiliza la variable de bucle chunk e
itera sobre la llamada a pd.read_csv(), pasando c_size a chunksize.
En el bucle interior, itera sobre la columna dada por colname en chunk utilizando un bucle for. Utiliza
la variable de bucle entry.
Llama a la función count_entries() pasándole el nombre de archivo '[Link]', el tamaño de
fragmentos 10 y el nombre de la columna que se debe contar, 'lang'. Asigna el resultado de la llamada
a la variable result_counts.
# Define count_entries()
def count_entries(csv_file, c_size, colname):
"""Return a dictionary with counts of
occurrences as value for each key."""
# Initialize an empty dictionary: counts_dict
counts_dict = {}
# Iterate over the file chunk by chunk
for chunk in pd.read_csv(csv_file, chunksize=c_size):
# Iterate over the column in DataFrame
for entry in chunk[colname]:
if entry in counts_dict.keys():
counts_dict[entry] += 1
else:
counts_dict[entry] = 1
# Return counts_dict
return counts_dict
# Call count_entries(): result_counts
result_counts = count_entries('[Link]', 10, 'lang')
# Print result_counts
print(result_counts)
out:
{'en': 97, 'et': 1, 'und': 2}
La función count_entries() se define con tres parámetros: csv_file, c_size y colname. Estos
parámetros permiten especificar el archivo CSV a procesar, el tamaño de los fragmentos de datos
que se leerán a la vez, y el nombre de la columna cuyos valores queremos contar.
2. Inicialización del diccionario counts_dict:
Se crea un diccionario vacío llamado counts_dict. Este diccionario se utilizará para almacenar la
cantidad de ocurrencias de cada valor en la columna especificada.
3. Iteración sobre el archivo CSV en fragmentos:
Se utiliza un bucle for para iterar sobre el archivo CSV, leyendo fragmentos de datos del tamaño
especificado por c_size usando pd.read_csv(csv_file, chunksize=c_size). Esto permite manejar
archivos grandes sin cargar todo el archivo en memoria de una sola vez.
4. Iteración sobre la columna especificada en cada fragmento:
Dentro del bucle que procesa cada fragmento, se utiliza otro bucle for para iterar sobre los valores de
la columna especificada por colname en el fragmento actual (chunk[colname]).
Para cada valor (entry) en la columna, se verifica si ya existe como clave en counts_dict. Si existe, se
incrementa su valor en 1. Si no existe, se añade al diccionario con un valor inicial de 1.
5. Retorno del diccionario counts_dict:
Una vez que se han procesado todos los fragmentos y se han contado todas las ocurrencias, la
función devuelve el diccionario counts_dict, que contiene la cantidad de veces que aparece cada
valor en la columna especificada.
6. Llamada a la función y almacenamiento del resultado:
La función count_entries() se llama con los argumentos '[Link]', 10, y 'lang'. Esto significa que se
procesará el archivo [Link] en fragmentos de 10 filas, contando las ocurrencias de cada valor en
la columna 'lang'.
El resultado de esta llamada se almacena en la variable result_counts.
Instrucciones
Utilizando el rango de números de 0 a 9 como iterable y i como variable de iterador, escribe una
comprensión de listas que produzca una lista de números formada por los valores al cuadrado de i.
out:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Comprensiones de listas anidadas
¡Estupendo! En este punto, dominas la sintaxis básica de las comprensiones de listas. Mejoremos un
poco más tus competencias de escritura de código. En este ejercicio, escribirás una comprensión de
listas dentro de otra comprensión de listas: son las comprensiones de listas anidadas. Parece un
poco complicado, pero puedes hacerlo. Apartémonos un rato de las cadenas. Una de las formas en
las que se pueden utilizar las listas es la representación de objetos multidimensionales como
las matrices. Las matrices pueden representarse como una lista de listas en Python. Por ejemplo, una
matriz de 5 × 5 con valores de 0 a 4 en cada fila puede escribirse como:
Tu tarea consiste en crear de nuevo esta matriz utilizando comprensiones de listas anidadas.
Recuerda que puedes crear una de las filas de la matriz con una sola comprensión de listas. Para
crear la lista de listas, solo tienes que proporcionar la comprensión de listas como expresión de
salida de la comprensión de listas general:
Instrucciones
En la comprensión de listas interior (es decir, la expresión de salida de la comprensión de listas
anidada), crea una lista de valores de 0 a 4 utilizando range(). Utiliza col como variable de iterador.
En la parte iterable de tu comprensión de listas anidada, utiliza range() para contar 5 filas: es decir,
crea una lista de valores de 0 a 4. Utiliza row como variable de iterador; ten en cuenta que no
necesitarás esta variable para crear valores en la lista de listas.
out:
"[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]"
1. Comprensión de listas anidada: La solución utiliza una comprensión de listas anidada para crear
una matriz de 5x5. Una comprensión de listas anidada es una forma concisa de crear listas dentro de
listas.
2. Expresión de salida (interior): La parte interior de la comprensión de listas es [col for col in
range(5)]. Aquí, col es la variable de iterador que toma valores de 0 a 4 gracias a range(5). Esto
significa que para cada iteración, se crea una lista que contiene los números [0, 1, 2, 3, 4].
3. Parte iterable (exterior): La parte exterior de la comprensión de listas es for row in range(5).
Aquí, row es la variable de iterador que también toma valores de 0 a 4 debido a range(5). Sin embargo,
en este caso, row no se utiliza directamente dentro de la expresión de salida. En su lugar, se utiliza
para repetir la creación de la lista interior cinco veces, una por cada valor de row.
4. Resultado final: Al combinar ambas partes, la comprensión de listas anidada crea una lista de
listas (una matriz) donde cada fila es [0, 1, 2, 3, 4], y hay cinco de estas filas en total. Esto da como
resultado una matriz de 5x5.
5. Impresión de la matriz: Finalmente, el bucle for row in matrix: print(row) recorre cada fila de la
matriz y la imprime, mostrando cada fila de la matriz en una línea separada.
Esta solución cumple con los requisitos del ejercicio al crear una matriz de 5x5 donde cada fila
contiene los números del 0 al 4.
Uso de condicionales en comprensiones (1)
Has estado utilizando comprensiones de listas para crear listas de valores, a veces usando
operaciones para crear estos valores.
Un mecanismo interesante de las comprensiones de listas es que también puedes crear listas con
valores que cumplan solo determinada condición. Una forma de hacerlo es utilizar condicionales en
variables de iterador. En este ejercicio, harás exactamente eso.
Recuerda del vídeo que puedes aplicar una declaración condicional para probar la variable de
iterador añadiendo una declaración if en la parte de expresión de predicado opcional después de la
declaración for en la comprensión:
Utilizarás esta receta para escribir una comprensión de listas para este ejercicio. Se te da la lista de
cadenas fellowship y, utilizando una comprensión de listas, crearás una lista que solo incluya los
miembros de fellowship que tengan 7 caracteres o más.
Instrucciones
out:
['samwise', 'aragorn', 'legolas', 'boromir']
Uso de condicionales en comprensiones (2)
Instrucciones
En la expresión de salida, mantén la cadena como está si el número de caracteres es >=7; de lo
contrario, sustitúyela por una cadena vacía, es decir, '' o "".
out:
# Print the new list print(new_fellowship)
['', 'samwise', '', 'aragorn', 'legolas', 'boromir', '']
Comprensiones de diccionarios
Las comprensiones no están relegadas al mundo de las listas. Hay muchos otros objetos que puedes
crear utilizando comprensiones, como los diccionarios, objetos omnipresentes en la ciencia de
datos. En este ejercicio, crearás un diccionario utilizando la sintaxis de comprensión. En este caso, la
comprensión se denomina comprensión de diccionarios. Recuerda que la principal diferencia entre
una comprensión de listas y una comprensión de diccionarios es el uso de llaves, {}, en lugar de [].
Además, los miembros del diccionario se crean utilizando dos puntos, :, como en <key> : <value>. Se
te da la lista de cadenas fellowship y, utilizando una comprensión de diccionarios, debes crear un
diccionario con los miembros de la lista como claves y la longitud de cada cadena como los valores
correspondientes.
Instrucciones
Crea una comprensión de diccionarios en la que la clave sea una cadena de fellowship y el valor sea
la longitud de la cadena. Recuerda utilizar la sintaxis <key> : <value> en la parte de la expresión de
salida de la comprensión para crear los miembros del diccionario. Utiliza member como variable de
iterador.
out:
{'frodo': 5, 'samwise': 7, 'merry': 5, 'aragorn': 7, 'legolas': 7, 'boromir': 7, 'gimli': 5}
Escribir tus propias expresiones de generador
Ya sabes lo que son los generadores y las expresiones de generador, y en qué se diferencian de las
comprensiones de listas. En este ejercicio, practicarás la creación de expresiones de generador por
tu cuenta. Recuerda que las expresiones de generador tienen básicamente la misma sintaxis que las
comprensiones de listas, excepto en que utilizan paréntesis, (), en lugar de corchetes, []. Esto debería
hacer que las cosas te resulten familiares. Además, si alguna vez has iterado sobre un diccionario
con .items(), o has utilizado la función range(), por ejemplo, ya habrás utilizado generadores sin
saberlo. Cuando utilizas estas funciones, Python crea generadores por ti de manera interna. Ahora
empezarás por lo fácil, creando un objeto generador que produzca valores numéricos.
Instrucciones
Crea un objeto generador que produzca valores de 0 a 30. Asigna el resultado a result y
utiliza num como variable de iterador en la expresión de generador.
Imprime los 5 primeros valores utilizando next() adecuadamente en print().
Imprime los demás valores utilizando un bucle for para iterar sobre el objeto generador.
out:
# Print the rest of the values for value in result: print(value)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Cambio de la salida en expresiones de generador
¡Estupendo! En este punto, ya sabes cómo escribir una expresión de generador básica. En este
ejercicio, llevarás esta idea un poco más lejos añadiéndola a la expresión de salida de una expresión
de generador. Como las expresiones de generador y las comprensiones de listas tienen una sintaxis
tan parecida, esta debería ser una tarea familiar para ti. Se te da la lista de cadenas lannister y,
mediante una expresión de generador, debes crear un objeto generador en el que iterarás para
imprimir sus valores.
Instrucciones
Escribe una expresión de generador que genere las longitudes de cada cadena en lannister.
Utiliza person como variable de iterador. Asigna el resultado a .
Proporciona el iterable correcto al bucle for para imprimir los valores del objeto generador.
out:
65567
Creación de un generador
En los ejercicios anteriores, te has ocupado principalmente de escribir expresiones de generador, que
utilizan la sintaxis de la comprensión. Poder utilizar la sintaxis de la comprensión para las
expresiones de generador te ha facilitado mucho el trabajo. Ahora, recuerda del vídeo que no solo hay
expresiones de generador, sino también funciones de generador. Las funciones de generador son
funciones que, igual que las expresiones de generador, producen una serie de valores en lugar de
devolver un único valor. Una función de generador se define como una función normal, pero, cuando
genera un valor, utiliza la palabra clave yield en lugar de return. En este ejercicio, crearás una función
de generador con un mecanismo similar al de la expresión de generador que definiste en el ejercicio
anterior:
Instrucciones
Completa el encabezado de función de la función get_lengths(), que tiene un único
parámetro, input_list.
En el bucle for de la definición de función, aplica yield a la longitud de las cadenas en input_list.
Completa la parte iterable del bucle for para imprimir los valores generados por la función de
generador get_lengths(). Proporciona la llamada a get_lengths(), pasando la lista lannister.
out:
65567
Comprensiones de listas para datos con marca temporal
Ahora utilizarás lo que has aprendido en este capítulo para resolver un sencillo problema de
extracción de datos. En este ejercicio también conocerás la estructura de datos Serie de pandas. No
nos extenderemos mucho sobre ella aquí, pero debes saber que es que es una estructura de datos
con la que trabajarás muchas veces al analizar datos de DataFrames de pandas. Las columnas del
DataFrame son como matrices unidimensionales llamadas series. En este ejercicio, utilizarás una
comprensión de listas para extraer la hora de los datos de Twitter con marca temporal. El paquete
pandas se ha importado como pd y el archivo '[Link]' se ha importado como DataFrame df para
que lo uses.
Instrucciones
Extrae la columna 'created_at' de df y asigna el resultado a tweet_time. Dato curioso: la columna
extraída de tweet_time es aquí la estructura de datos Serie.
Crea una comprensión de listas que extraiga la hora de cada fila de tweet_time. Cada fila es una
cadena que representa una marca temporal, y accederás a los caracteres 12-19 de la cadena para
extraer la hora. Utiliza entry como variable de iterador y asigna el resultado a tweet_clock_time.
Recuerda que Python utiliza la indexación de base 0.
Genial, has extraído correctamente los datos de interés (la hora) de un DataFrame de pandas.
Retoquemos tu trabajo añadiendo un condicional que especifique mejor qué entradas deben
seleccionarse. En este ejercicio, utilizarás una comprensión de listas para extraer la hora de los datos
de Twitter con marca temporal. Añadirás una expresión condicional a la comprensión de listas para
seleccionar solo las horas en las que entry[17:19] sea igual a '19'. El paquete pandas se ha importado
como pd y el archivo '[Link]' se ha importado como DataFrame df para que lo uses.
Instrucciones
Extrae la columna 'created_at' de df y asigna el resultado a tweet_time.
Crea una comprensión de listas que extraiga la hora de cada fila de tweet_time. Cada fila es una
cadena que representa una marca temporal, y accederás a los caracteres 12-19 de la cadena para
extraer la hora. Utiliza entry como variable de iterador y asigna el resultado a tweet_clock_time.
Además, añade una expresión condicional que compruebe si entry[17:19] es igual a '19'.
Iterador entry: La variable entry representa cada elemento (o fila) de tweet_time, que es una cadena
de texto que contiene una marca temporal completa.
Extracción de la hora: entry[11:19] extrae los caracteres del índice 11 al 18 de cada cadena entry.
Estos índices corresponden a la parte de la cadena que representa la hora en formato HH:MM:SS.
Condición: if entry[17:19] == '19' es una expresión condicional que filtra las entradas. Solo se
incluirán en tweet_clock_time aquellas entradas donde los caracteres en las posiciones 17 a 18 (que
representan los segundos) sean iguales a '19'.