Este es el tercer artículo de una breve serie sobre el desarrollo de paneles de datos utilizando las últimas herramientas de desarrollo basadas en Python, Streamlit, Gradio y Taipy.
El conjunto de datos de origen para cada tablero es el mismo, pero almacenado en diferentes formatos. En la medida de lo posible, intentaré hacer que los diseños de tablero reales para cada herramienta se parezcan entre sí y tendrán la misma funcionalidad.
Ya he escrito las versiones Streamlit y Gradio. La versión Streamlit obtiene sus datos de origen de una base de datos de Postgres. Las versiones de Gradio y Taipy obtienen sus datos de un archivo CSV. Puede encontrar enlaces a esos otros artículos al final de este.
¿Qué es Taipy?
Taipy es un marco web relativamente nuevo basado en Python que se hizo prominente hace un par de años. Según su sitio web, Taipy es …
“… Una biblioteca de Python de código abierto para construir front-end y back-end listos para la producción en muy poco tiempo. ¡No se requiere conocimiento del desarrollo web!“
El público objetivo para Taipy son los científicos de datos, los profesionales de aprendizaje automático e ingenieros de datos que pueden no tener una experiencia extensa en el desarrollo de aplicaciones frontales, pero generalmente tienen fluidez en Python. Taipy hace que sea razonablemente fácil crear front-end usando Python, por lo que es un beneficio mutuo.
Puede comenzar a usar Taipy gratis. Si necesita usarlo como parte de una empresa, con soporte dedicado y escalabilidad, los planes pagos están disponibles mensualmente o anualmente. Su sitio web proporciona más información, a la que vincularé al final de este artículo.
¿Por qué usar Taipy sobre Gradio o Streamlit?
Como he mostrado en este y en los otros dos artículos, puede desarrollar una salida muy similar utilizando los tres marcos, por lo que plantea la pregunta de por qué usar uno sobre el otro.
Si bien Gradio se destaca para crear rápidamente ML Demos y Streamlit es brillante para la exploración de datos interactivos, ambos operan en un principio de simplicidad que puede convertirse en una limitación a medida que crece la ambición de su aplicación. Taipy entra en la imagen cuando su proyecto necesita graduarse de un script o demostración simple en una aplicación robusta, de rendimiento y mantenible.
Debe considerar fuertemente elegir a Taipy sobre simplificación/gradio si,
- El rendimiento de su aplicación es crítico
- Su archivo de script único se está volviendo inmanejamente largo y complejo.
- Debe crear aplicaciones de varias páginas con navegación compleja.
- Su aplicación requiere un análisis de escenarios de “si” o una ejecución compleja de la tubería.
- Está creando una herramienta de producción para usuarios comerciales, no solo un tablero exploratorio interno.
- Está trabajando en un equipo y necesita una base de código limpia y mantenible.
En resumen, elija Gradio para demostraciones. Elegir Racionalizar para exploración interactiva. Elegir Taipy Cuando está listo para crear aplicaciones de datos empresariales de alto rendimiento, escalable y de grado de producción.
Lo que desarrollaremos
Estamos desarrollando un tablero de datos. Nuestros datos de origen serán un solo archivo CSV que contenga 100,000 registros de ventas sintéticas.
La fuente real de los datos no eso importante. Se podría almacenar fácilmente como un archivo parquet, en SQLite o Postgres, o cualquier base de datos a la que pueda conectarse.
Así es como se verá nuestro tablero final.
Hay cuatro secciones principales.
- La fila superior permite al usuario seleccionar fechas de inicio y finalización específicas y/o categorías de productos utilizando recolectores de fecha y una lista desplegable, respectivamente.
- La segunda fila, “Métricas clave,“ proporciona un resumen de nivel superior de los datos seleccionados.
- El Visualizaciones La sección permite al usuario seleccionar uno de los tres gráficos para mostrar el conjunto de datos de entrada.
- El Datos sin procesar La sección es exactamente lo que dice ser. Esta representación tabular de los datos elegidos ve efectivamente el archivo de datos CSV subyacente.
Usar el tablero es fácil. Inicialmente, se muestran estadísticas para todo el conjunto de datos. El usuario puede reducir el enfoque de datos utilizando los 3 campos de elección en la parte superior de la pantalla. Los gráficos, las métricas clave y las secciones de datos sin procesar se actualizan dinámicamente para reflejar las elecciones del usuario.
Los datos de origen
Como se mencionó, los datos de origen del tablero están contenidos en un solo archivo de valores separados por comas (CSV). Los datos constan de 100,000 registros sintéticos relacionados con las ventas. Aquí están los primeros diez registros del archivo.
+----------+------------+------------+----------------+------------+---------------+------------+----------+-------+--------------------+
| order_id | order_date | customer_id| customer_name | product_id | product_names | categories | quantity | price | total |
+----------+------------+------------+----------------+------------+---------------+------------+----------+-------+--------------------+
| 0 | 01/08/2022 | 245 | Customer_884 | 201 | Smartphone | Electronics| 3 | 90.02 | 270.06 |
| 1 | 19/02/2022 | 701 | Customer_1672 | 205 | Printer | Electronics| 6 | 12.74 | 76.44 |
| 2 | 01/01/2017 | 184 | Customer_21720 | 208 | Notebook | Stationery | 8 | 48.35 | 386.8 |
| 3 | 09/03/2013 | 275 | Customer_23770 | 200 | Laptop | Electronics| 3 | 74.85 | 224.55 |
| 4 | 23/04/2022 | 960 | Customer_23790 | 210 | Cabinet | Office | 6 | 53.77 | 322.62 |
| 5 | 10/07/2019 | 197 | Customer_25587 | 202 | Desk | Office | 3 | 47.17 | 141.51 |
| 6 | 12/11/2014 | 510 | Customer_6912 | 204 | Monitor | Electronics| 5 | 22.5 | 112.5 |
| 7 | 12/07/2016 | 150 | Customer_17761 | 200 | Laptop | Electronics| 9 | 49.33 | 443.97 |
| 8 | 12/11/2016 | 997 | Customer_23801 | 209 | Coffee Maker | Electronics| 7 | 47.22 | 330.54 |
| 9 | 23/01/2017 | 151 | Customer_30325 | 207 | Pen | Stationery | 6 | 3.5 | 21 |
+----------+------------+------------+----------------+------------+---------------+------------+----------+-------+--------------------+
Y aquí hay algún código de Python que puede usar para generar un conjunto de datos. Utiliza las bibliotecas Numpy y Pandas Python, así que asegúrese de que ambos estén instalados antes de ejecutar el código.
# generate the 100000 record CSV file
#
import polars as pl
import numpy as np
from datetime import datetime, timedelta
def generate(nrows: int, filename: str):
names = np.asarray(
[
"Laptop",
"Smartphone",
"Desk",
"Chair",
"Monitor",
"Printer",
"Paper",
"Pen",
"Notebook",
"Coffee Maker",
"Cabinet",
"Plastic Cups",
]
)
categories = np.asarray(
[
"Electronics",
"Electronics",
"Office",
"Office",
"Electronics",
"Electronics",
"Stationery",
"Stationery",
"Stationery",
"Electronics",
"Office",
"Sundry",
]
)
product_id = np.random.randint(len(names), size=nrows)
quantity = np.random.randint(1, 11, size=nrows)
price = np.random.randint(199, 10000, size=nrows) / 100
# Generate random dates between 2010-01-01 and 2023-12-31
start_date = datetime(2010, 1, 1)
end_date = datetime(2023, 12, 31)
date_range = (end_date - start_date).days
# Create random dates as np.array and convert to string format
order_dates = np.array([(start_date + timedelta(days=np.random.randint(0, date_range))).strftime('%Y-%m-%d') for _ in range(nrows)])
# Define columns
columns = {
"order_id": np.arange(nrows),
"order_date": order_dates,
"customer_id": np.random.randint(100, 1000, size=nrows),
"customer_name": [f"Customer_{i}" for i in np.random.randint(2**15, size=nrows)],
"product_id": product_id + 200,
"product_names": names[product_id],
"categories": categories[product_id],
"quantity": quantity,
"price": price,
"total": price * quantity,
}
# Create Polars DataFrame and write to CSV with explicit delimiter
df = pl.DataFrame(columns)
df.write_csv(filename, separator=',',include_header=True) # Ensure comma is used as the delimiter
# Generate 100,000 rows of data with random order_date and save to CSV
generate(100_000, "/mnt/d/sales_data/sales_data.csv")
Instalación y uso de Taipy
Instalar Taipy es fácil, pero antes de codificar, es una mejor práctica configurar un entorno de Python separado para todo su trabajo. Utilizo Miniconda para este propósito, pero no me siento libre de usar cualquier método que se adapte a su flujo de trabajo.
Si desea seguir la ruta de Miniconda y aún no la tiene, primero debe instalar Miniconda.
Una vez que se crea el entorno, cambie a él utilizando el ‘activar’ comando y luego ejecutar ‘PIP Instalar’ a Instale nuestras bibliotecas Python requeridas.
#create our test environment
(base) C:\Users\thoma>conda create -n taipy_dashboard python=3.12 -y
# Now activate it
(base) C:\Users\thoma>conda activate taipy_dashboard
# Install python libraries, etc ...
(taipy_dashboard) C:\Users\thoma>pip install taipy pandas
El código
Desglosaré el código en secciones y explicaré cada una a medida que avanzamos.
Sección 1
from taipy.gui import Gui
import pandas as pd
import datetime
# Load CSV data
csv_file_path = r"d:\sales_data\sales_data.csv"
try:
raw_data = pd.read_csv(
csv_file_path,
parse_dates=["order_date"],
dayfirst=True,
low_memory=False # Suppress dtype warning
)
if "revenue" not in raw_data.columns:
raw_data["revenue"] = raw_data["quantity"] * raw_data["price"]
print(f"Data loaded successfully: {raw_data.shape[0]} rows")
except Exception as e:
print(f"Error loading CSV: {e}")
raw_data = pd.DataFrame()
categories = ["All Categories"] + raw_data["categories"].dropna().unique().tolist()
# Define the visualization options as a proper list
chart_options = ["Revenue Over Time", "Revenue by Category", "Top Products"]
Este script prepara datos de ventas para su uso en nuestra aplicación de visualización de Taipy. Hace lo siguiente,
- Importa las bibliotecas y cargas externas requeridas y preprocesos nuestros datos de origen del CSV de entrada.
- Calcula métricas derivadas como los ingresos.
- Extrae opciones de filtrado relevantes (categorías).
- Define las opciones de visualización disponibles.
Sección 2
start_date = raw_data["order_date"].min().date() if not raw_data.empty else datetime.date(2020, 1, 1)
end_date = raw_data["order_date"].max().date() if not raw_data.empty else datetime.date(2023, 12, 31)
selected_category = "All Categories"
selected_tab = "Revenue Over Time" # Set default selected tab
total_revenue = "$0.00"
total_orders = 0
avg_order_value = "$0.00"
top_category = "N/A"
revenue_data = pd.DataFrame(columns=["order_date", "revenue"])
category_data = pd.DataFrame(columns=["categories", "revenue"])
top_products_data = pd.DataFrame(columns=["product_names", "revenue"])
def apply_changes(state):
filtered_data = raw_data[
(raw_data["order_date"] >= pd.to_datetime(state.start_date)) &
(raw_data["order_date"] <= pd.to_datetime(state.end_date))
]
if state.selected_category != "All Categories":
filtered_data = filtered_data[filtered_data["categories"] == state.selected_category]
state.revenue_data = filtered_data.groupby("order_date")["revenue"].sum().reset_index()
state.revenue_data.columns = ["order_date", "revenue"]
print("Revenue Data:")
print(state.revenue_data.head())
state.category_data = filtered_data.groupby("categories")["revenue"].sum().reset_index()
state.category_data.columns = ["categories", "revenue"]
print("Category Data:")
print(state.category_data.head())
state.top_products_data = (
filtered_data.groupby("product_names")["revenue"]
.sum()
.sort_values(ascending=False)
.head(10)
.reset_index()
)
state.top_products_data.columns = ["product_names", "revenue"]
print("Top Products Data:")
print(state.top_products_data.head())
state.raw_data = filtered_data
state.total_revenue = f"${filtered_data['revenue'].sum():,.2f}"
state.total_orders = filtered_data["order_id"].nunique()
state.avg_order_value = f"${filtered_data['revenue'].sum() / max(filtered_data['order_id'].nunique(), 1):,.2f}"
state.top_category = (
filtered_data.groupby("categories")["revenue"].sum().idxmax()
if not filtered_data.empty else "N/A"
)
def on_change(state, var_name, var_value):
if var_name in {"start_date", "end_date", "selected_category", "selected_tab"}:
print(f"State change detected: {var_name} = {var_value}") # Debugging
apply_changes(state)
def on_init(state):
apply_changes(state)
import taipy.gui.builder as tgb
def get_partial_visibility(tab_name, selected_tab):
return "block" if tab_name == selected_tab else "none"
Establece las fechas de inicio y finalización predeterminadas y la categoría inicial. Además, el gráfico inicial se mostrará como Ingresos con el tiempo. El marcador de posición y los valores iniciales también se establecen para lo siguiente:-
- Total_Revenue. Empezar a
"$0.00". - Total_orders. Empezar a
0. - AVG_ORDER_VALUE. Empezar a
"$0.00". - top_category. Empezar a
"N/A".
Se establecen marcos de datos vacíos para:-
- ingresos_data. Las columnas son
["order_date", "revenue"]. - category_data. Las columnas son
["categories", "revenue"]. - top_products_data. Las columnas son
["product_names", "revenue"].
El Aplicar_Changes la función está definida. Esta función se activa para actualizar el estado cuando se aplican filtros (como el rango de fechas o la categoría). Actualiza lo siguiente:-
- Tendencias de ingresos de series de tiempo.
- Distribución de ingresos en categorías.
- Los 10 productos principales por ingresos.
- Métricas resumidas (ingresos totales, pedidos totales, valor de pedido promedio, categoría superior).
El On_change FUNCIONES DE FUNCIONES siempre que se cambie cualquiera de los componentes seleccionables del usuario
El en_init FUNCIONES DE FUNCIONES cuando la aplicación se ejecuta por primera vez.
El get_partial_visibility La función determina el CSS display Propiedad para elementos de interfaz de usuario basado en la pestaña seleccionada.
Sección 3
with tgb.Page() as page:
tgb.text("# Sales Performance Dashboard", mode="md")
# Filters section
with tgb.part(class_name="card"):
with tgb.layout(columns="1 1 2"): # Arrange elements in 3 columns
with tgb.part():
tgb.text("Filter From:")
tgb.date("{start_date}")
with tgb.part():
tgb.text("To:")
tgb.date("{end_date}")
with tgb.part():
tgb.text("Filter by Category:")
tgb.selector(
value="{selected_category}",
lov=categories,
dropdown=True,
width="300px"
)
# Metrics section
tgb.text("## Key Metrics", mode="md")
with tgb.layout(columns="1 1 1 1"):
with tgb.part(class_name="metric-card"):
tgb.text("### Total Revenue", mode="md")
tgb.text("{total_revenue}")
with tgb.part(class_name="metric-card"):
tgb.text("### Total Orders", mode="md")
tgb.text("{total_orders}")
with tgb.part(class_name="metric-card"):
tgb.text("### Average Order Value", mode="md")
tgb.text("{avg_order_value}")
with tgb.part(class_name="metric-card"):
tgb.text("### Top Category", mode="md")
tgb.text("{top_category}")
tgb.text("## Visualizations", mode="md")
# Selector for visualizations with reduced width
with tgb.part(style="width: 50%;"): # Reduce width of the dropdown
tgb.selector(
value="{selected_tab}",
lov=["Revenue Over Time", "Revenue by Category", "Top Products"],
dropdown=True,
width="360px", # Reduce width of the dropdown
)
# Conditional rendering of charts based on selected_tab
with tgb.part(render="{selected_tab == 'Revenue Over Time'}"):
tgb.chart(
data="{revenue_data}",
x="order_date",
y="revenue",
type="line",
title="Revenue Over Time",
)
with tgb.part(render="{selected_tab == 'Revenue by Category'}"):
tgb.chart(
data="{category_data}",
x="categories",
y="revenue",
type="bar",
title="Revenue by Category",
)
with tgb.part(render="{selected_tab == 'Top Products'}"):
tgb.chart(
data="{top_products_data}",
x="product_names",
y="revenue",
type="bar",
title="Top Products",
)
# Raw Data Table
tgb.text("## Raw Data", mode="md")
tgb.table(data="{raw_data}")
Esta sección del código define el aspecto y el comportamiento de la página general y se divide en varias subsecciones
Definición de página
tgp.page (). Representa el contenedor principal del tablero, definiendo la estructura y los elementos de la página.
Diseño del tablero
- Muestra el título: “Panel de rendimiento de ventas” en modo markdown (
mode="md").
Sección de filtros
- Colocado dentro de un parte del estilo de la tarjeta que usa un diseño de 3 columnas-
tgb.layout(columns="1 1 2")– Para organizar los filtros.
Elementos de filtro
- Fecha de inicio. Un selector de citas
tgb.date("{start_date}")para seleccionar el inicio del rango de fechas. - Fecha de finalización. Un selector de citas
tgb.date("{end_date}")para elegir el final del rango de fechas. - Filtro de categoría.
- Un selector desplegable
tgb.selectorFiltrar datos por categorías. - Poblado usando
categoriesp.ej,"All Categories"y categorías disponibles del conjunto de datos.
Sección de métricas clave
Muestra estadísticas resumidas en cuatro tarjetas métricas arreglado en un diseño de 4 columnas:
- Ingresos totales. Muestra el
total_revenuevalor. - Total de pedidos. Muestra el número de pedidos únicos (
total_orders). - Valor de pedido promedio. Muestra el
avg_order_value. - Categoría superior. Muestra el nombre de la categoría que contribuye con la mayor cantidad de ingresos.
Sección de visualizaciones
- Un selector desplegable permite a los usuarios cambiar entre diferentes visualizaciones (por ejemplo, “ingresos con el tiempo”, “ingresos por categoría”, “productos principales”).
- El ancho desplegable se reduce para una interfaz de usuario compacta.
Representación condicional de gráficos
- Ingresos con el tiempo. Muestra el gráfico de línea
revenue_datamostrando tendencias de ingresos con el tiempo. - Ingresos por categoría. Muestra el gráfico de barras
category_dataPara visualizar la distribución de ingresos en las categorías. - Productos principales. Muestra el gráfico de barras
top_products_dataMostrando los 10 productos principales por ingresos.
Tabla de datos sin procesar
- Muestra el conjunto de datos sin procesar en un formato tabular.
- Actualizaciones dinámicas basadas en filtros aplicados por el usuario (p. Ej., Rango de fechas, categoría).
Sección 4
Gui(page).run(
title="Sales Dashboard",
dark_mode=False,
debug=True,
port="auto",
allow_unsafe_werkzeug=True,
async_mode="threading"
)
Esta sección final y corta representa la página para que se muestre en un navegador.
Ejecutando el código
Recopile todos los fragmentos de código anteriores y guárdelos en un archivo, por ejemplo, taipy-app.py. Asegúrese de que su archivo de datos de origen esté en la ubicación correcta y se haga referencia correctamente en su código. Luego ejecuta el módulo como cualquier otro código de Python escribiendo esto en un terminal de línea de comandos.
python taipy-app.py
Después de un segundo o dos, debe ver que se muestra una ventana de navegador con su aplicación de datos.
Resumen
En este artículo, he intentado proporcionar una guía completa para construir un tablero de rendimiento de ventas interactiva con Taipy utilizando un archivo CSV como datos de origen.
Le expliqué que Taipy es un marco moderno de código abierto basado en Python que simplifica la creación de paneles y aplicaciones basados en datos. También proporcioné algunas sugerencias sobre por qué es posible que desee usar Taipy sobre los otros dos marcos populares, Gradio y Streamlit.
El tablero que desarrollé permite a los usuarios filtrar rangos de datos por fecha y categorías de productos, ver métricas clave, como ingresos totales y categorías de alto rendimiento, explorar visualizaciones como tendencias de ingresos y productos superiores, y navegar a través de datos sin procesar con paginación.
Esta guía proporciona una implementación integral, que cubre todo el proceso desde la creación de datos de muestra hasta el desarrollo de funciones de Python para consultar datos, generar gráficos y manejar la entrada del usuario. Este enfoque paso a paso demuestra cómo aprovechar las capacidades de Taipy para crear paneles de uso de usuarios y dinámicos, lo que lo hace ideal para ingenieros de datos y científicos que desean construir aplicaciones de datos interactivas.
Aunque utilicé un archivo CSV para mi fuente de datos, modificar el código para usar otra fuente de datos, como un sistema de gestión de bases de datos relacionales (RDBMS) como SQLite, debe ser sencillo.
Para obtener más información sobre Taipy, su sitio web es https://taipy.io/
Para ver mis otros dos artículos TDS en la construcción de paneles de datos utilizando Gradio y Streamlit, haga clic en los enlaces a continuación.