Salida de datos estructurados para el análisis de datos

Intermediate

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

Introducción

Esta sección es un ligero desvío, pero cuando trabajas con datos, a menudo quieres producir una salida estructurada (tablas, etc.). Por ejemplo:

      Nombre      Acciones        Precio
----------  ----------  -----------
        AA         100        32,20
       IBM          50        91,10
       CAT         150        83,44
      MSFT         200        51,23
        GE          95        40,37
      MSFT          50        65,10
       IBM         100        70,44
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 intermedio con una tasa de finalización del 75%. Ha recibido una tasa de reseñas positivas del 80% por parte de los estudiantes.

Formateo de cadenas

Una forma de formatear cadenas en Python 3.6+ es con f-strings.

>>> nombre = 'IBM'
>>> acciones = 100
>>> precio = 91.1
>>> f'{nombre:>10s} {acciones:>10d} {precio:>10.2f}'
'       IBM        100      91.10'
>>>

La parte {expresión:formato} es reemplazada.

Se suele utilizar con print.

print(f'{nombre:>10s} {acciones:>10d} {precio:>10.2f}')

Códigos de formato

Los códigos de formato (después del : dentro de {}) son similares a printf() de C. Los códigos comunes incluyen:

d       Entero decimal
b       Entero binario
x       Entero hexadecimal
f       Flotante como [-]m.dddddd
e       Flotante como [-]m.dddddde+-xx
g       Flotante, pero uso selectivo de notación científica
s       Cadena
c       Carácter (desde un entero)

Los modificadores comunes ajustan el ancho del campo y la precisión decimal. Esta es una lista parcial:

:>10d   Entero alineado a la derecha en un campo de 10 caracteres
:<10d   Entero alineado a la izquierda en un campo de 10 caracteres
:^10d   Entero centrado en un campo de 10 caracteres
:0.2f   Flotante con precisión de 2 dígitos

Formateo de diccionarios

Puedes usar el método format_map() para aplicar el formateo de cadenas a un diccionario de valores:

>>> s = {
    'nombre': 'IBM',
    'acciones': 100,
    'precio': 91.1
}
>>> '{nombre:>10s} {acciones:10d} {precio:10.2f}'.format_map(s)
'       IBM        100      91.10'
>>>

Utiliza los mismos códigos que f-strings pero toma los valores del diccionario suministrado.

Método format()

Existe un método format() que puede aplicar formateo a argumentos posicionales o argumentos de palabras clave.

>>> '{nombre:>10s} {acciones:10d} {precio:10.2f}'.format(nombre='IBM', acciones=100, precio=91.1)
'       IBM        100      91.10'
>>> '{:>10s} {:10d} {:10.2f}'.format('IBM', 100, 91.1)
'       IBM        100      91.10'
>>>

Para ser franco, format() es un poco verboso. Prefiero f-strings.

Formateo estilo C

También puedes usar el operador de formateo %.

>>> 'El valor es %d' % 3
'The value is 3'
>>> '%5d %-5d %10d' % (3,4,5)
'    3 4              5'
>>> '%0.2f' % (3.1415926,)
'3.14'

Esto requiere un solo elemento o una tupla en el lado derecho. Los códigos de formato también se basan en printf() de C.

Nota: Este es el único formateo disponible para cadenas de bytes.

>>> b'%s tiene %d mensajes' % (b'Dave', 37)
b'Dave has 37 messages'
>>> b'%b tiene %d mensajes' % (b'Dave', 37)  ## %b puede usarse en lugar de %s
b'Dave has 37 messages'
>>>

Ejercicio 2.8: Cómo formatear números

Un problema común al imprimir números es especificar el número de decimales. Una forma de solucionarlo es usar f-strings. Prueba estos ejemplos:

>>> valor = 42863.1
>>> print(valor)
42863.1
>>> print(f'{valor:0.4f}')
42863.1000
>>> print(f'{valor:>16.2f}')
        42863.10
>>> print(f'{valor:<16.2f}')
42863.10
>>> print(f'{valor:*>16,.2f}')
*******42,863.10
>>>

La documentación completa sobre los códigos de formateo utilizados en f-strings se puede encontrar aquí. A veces, el formateo también se realiza utilizando el operador % de cadenas.

>>> print('%0.4f' % valor)
42863.1000
>>> print('%16.2f' % valor)
        42863.10
>>>

La documentación sobre los diversos códigos utilizados con % se puede encontrar aquí.

Aunque se utiliza comúnmente con print, el formateo de cadenas no está vinculado a la impresión. Si quieres guardar una cadena formateada, simplemente asígnala a una variable.

>>> f = '%0.4f' % valor
>>> f
'42863.1000'
>>>

Ejercicio 2.9: Recopilando datos

En el Ejercicio 2.7, escribiste un programa llamado report.py que calculaba la ganancia/perdida de una cartera de acciones. En este ejercicio, vas a comenzar a modificarlo para generar una tabla como esta:

      Nombre     Acciones      Precio     Cambio
---------- ---------- ---------- ----------
        AA        100       9.22     -22.98
       IBM         50     106.28      15.18
       CAT        150      35.46     -47.98
      MSFT        200      20.89     -30.34
        GE         95      13.48     -26.89
      MSFT         50      20.89     -44.21
       IBM        100     106.28      35.84

En este informe, "Precio" es el precio actual de la acción y "Cambio" es el cambio en el precio de la acción desde el precio de compra inicial.

Para generar el informe anterior, primero querrás recopilar todos los datos mostrados en la tabla. Escribe una función make_report() que tome una lista de acciones y un diccionario de precios como entrada y devuelva una lista de tuplas que contengan las filas de la tabla anterior.

Agrega esta función a tu archivo report.py. Aquí es cómo debería funcionar si la pruebas interactiva:

>>> portfolio = read_portfolio('/home/labex/project/portfolio.csv')
>>> prices = read_prices('/home/labex/project/prices.csv')
>>> report = make_report(portfolio, prices)
>>> for r in report:
        print(r)

('AA', 100, 9.22, -22.980000000000004)
('IBM', 50, 106.28, 15.180000000000007)
('CAT', 150, 35.46, -47.98)
('MSFT', 200, 20.89, -30.339999999999996)
('GE', 95, 13.48, -26.889999999999997)
...
>>>

Ejercicio 2.10: Imprimiendo una tabla formateada

Repite el bucle for del Ejercicio 2.9, pero cambia la instrucción print para formatear las tuplas.

>>> for r in report:
        print('%10s %10d %10.2f %10.2f' % r)

          AA        100       9.22     -22.98
         IBM         50     106.28      15.18
         CAT        150      35.46     -47.98
        MSFT        200      20.89     -30.34
...
>>>

También puedes expandir los valores y usar f-strings. Por ejemplo:

>>> for name, shares, price, change in report:
        print(f'{name:>10s} {shares:>10d} {price:>10.2f} {change:>10.2f}')

          AA        100       9.22     -22.98
         IBM         50     106.28      15.18
         CAT        150      35.46     -47.98
        MSFT        200      20.89     -30.34
...
>>>

Toma las declaraciones anteriores y agréguelas a tu programa report.py. Haz que tu programa tome la salida de la función make_report() e imprima una tabla formateada adecuadamente como se muestra.

Ejercicio 2.11: Agregando algunos encabezados

Supongamos que tienes una tupla de nombres de encabezados como esta:

encabezados = ('Nombre', 'Acciones', 'Precio', 'Cambio')

Agrega código a tu programa que tome la tupla de encabezados anterior y cree una cadena donde cada nombre de encabezado esté alineado a la derecha en un campo de 10 caracteres de ancho y cada campo esté separado por un solo espacio.

'      Nombre     Acciones      Precio      Cambio'

Escribe código que tome los encabezados y cree la cadena de separación entre los encabezados y los datos siguientes. Esta cadena es simplemente un montón de caracteres "-" debajo de cada nombre de campo. Por ejemplo:

'---------- ---------- ---------- -----------'

Cuando termines, tu programa debería producir la tabla mostrada al principio de este ejercicio.

      Nombre     Acciones      Precio     Cambio
---------- ---------- ---------- ----------
        AA        100       9.22     -22.98
       IBM         50     106.28      15.18
       CAT        150      35.46     -47.98
      MSFT        200      20.89     -30.34
        GE         95      13.48     -26.89
      MSFT         50      20.89     -44.21
       IBM        100     106.28      35.84

Ejercicio 2.12: Desafío de formateo

¿Cómo modificarias tu código para que el precio incluya el símbolo de moneda ($) y la salida se vea así:

      Nombre     Acciones      Precio     Cambio
---------- ---------- ---------- ----------
        AA        100      $9.22     -22.98
       IBM         50    $106.28      15.18
       CAT        150     $35.46     -47.98
      MSFT        200     $20.89     -30.34
        GE         95     $13.48     -26.89
      MSFT         50     $20.89     -44.21
       IBM        100    $106.28      35.84

Resumen

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