st.dataframe: tabla interactiva
st.dataframe renderiza un DataFrame de Pandas como una tabla HTML interactiva con ordenación de columnas, redimensionamiento, scroll y búsqueda. Es la forma principal de mostrar datos tabulares en Streamlit, ya que permite al usuario explorar los datos directamente en la interfaz sin necesidad de escribir código adicional.
La tabla generada soporta interacciones avanzadas como ordenar columnas al hacer clic en el encabezado, redimensionar el ancho de columna arrastrando los bordes y navegar por conjuntos de datos grandes con scroll vertical y horizontal:
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame({
"producto": ["Laptop Pro", "Monitor 27", "Teclado", "Ratón", "Auriculares"],
"precio": [1299.99, 349.50, 129.00, 49.90, 89.99],
"stock": [25, 12, 78, 156, 43],
"activo": [True, True, True, False, True],
"web": ["https://ejemplo.com/p1", "https://ejemplo.com/p2", None, None, "https://ejemplo.com/p5"]
})
st.dataframe(
df,
use_container_width=True,
hide_index=True,
height=250
)
El parámetro hide_index=True oculta la columna de índice de Pandas, que en la mayoría de dashboards es un detalle técnico que no aporta valor al usuario final. El parámetro height fija la altura del widget en píxeles, evitando que tablas con muchas filas expandan la página de forma descontrolada.
flowchart TD
A[DataFrame Pandas] --> B[st.dataframe argumentos]
B --> C[use_container_width hide_index height]
B --> D[column_config dict]
B --> E[on_select rerun]
D --> F[NumberColumn formato divisa]
D --> G[ProgressColumn barra valor]
D --> H[LinkColumn url]
D --> I[ImageColumn miniatura]
D --> J[SelectboxColumn editable]
E --> K[Selecciona filas múltiple]
K --> L[selection.rows en session_state]
L --> M[Lógica downstream basada en selección]
F --> N[Tabla interactiva ordenable buscable]
G --> N
H --> N
st.column_config: personalización de columnas
st.column_config permite especificar el tipo de renderizado de cada columna, transformando datos en bruto en representaciones visuales ricas. Cada tipo de columna renderiza los datos de forma diferente: barras de progreso para porcentajes, checkboxes para booleanos, enlaces clicables para URLs, mini gráficos para listas de valores, entre otros:
import streamlit as st
import pandas as pd
df = pd.DataFrame({
"nombre": ["Ana García", "Luis Martín", "María López"],
"email": ["ana@emp.com", "luis@emp.com", "maria@emp.com"],
"salario": [45000, 62000, 38000],
"rendimiento": [0.87, 0.92, 0.79],
"activo": [True, True, False],
"contratacion": ["2021-03-15", "2019-08-22", "2023-01-10"],
"web": ["https://linkedin.com", None, "https://github.com"]
})
st.dataframe(
df,
use_container_width=True,
hide_index=True,
column_config={
"nombre": st.column_config.TextColumn("Nombre completo", width="medium"),
"email": st.column_config.TextColumn("Correo electrónico"),
"salario": st.column_config.NumberColumn(
"Salario anual",
format="€%,.0f",
min_value=0,
max_value=200000
),
"rendimiento": st.column_config.ProgressColumn(
"Rendimiento",
format="%.0f%%",
min_value=0,
max_value=1
),
"activo": st.column_config.CheckboxColumn("Activo"),
"contratacion": st.column_config.DateColumn("Fecha de contratación", format="DD/MM/YYYY"),
"web": st.column_config.LinkColumn("Perfil online", display_text="Ver perfil")
}
)
Tipos de column_config disponibles
Streamlit proporciona un amplio catálogo de tipos de columna, cada uno diseñado para un tipo de dato específico. A continuación se listan los principales tipos con su constructor:
import streamlit as st
# Todos los tipos de configuración de columna
ejemplos = {
"TextColumn": st.column_config.TextColumn("Texto", max_chars=50),
"NumberColumn": st.column_config.NumberColumn("Número", format="€%.2f"),
"DateColumn": st.column_config.DateColumn("Fecha", format="YYYY-MM-DD"),
"DatetimeColumn": st.column_config.DatetimeColumn("Fecha y hora"),
"TimeColumn": st.column_config.TimeColumn("Hora"),
"CheckboxColumn": st.column_config.CheckboxColumn("Booleano"),
"ProgressColumn": st.column_config.ProgressColumn("Progreso", min_value=0, max_value=1),
"ImageColumn": st.column_config.ImageColumn("Imagen"),
"LinkColumn": st.column_config.LinkColumn("Enlace"),
"ListColumn": st.column_config.ListColumn("Lista"),
"SelectboxColumn": st.column_config.SelectboxColumn("Selección", options=["A", "B", "C"]),
"BarChartColumn": st.column_config.BarChartColumn("Mini gráfico de barras"),
"LineChartColumn": st.column_config.LineChartColumn("Mini gráfico de líneas"),
"AreaChartColumn": st.column_config.AreaChartColumn("Mini gráfico de área"),
}
Los tipos BarChartColumn, LineChartColumn y AreaChartColumn son especialmente interesantes porque permiten incrustar mini gráficos (sparklines) dentro de las celdas de la tabla, mostrando tendencias sin ocupar espacio adicional en el layout.
Selección de filas con on_select
El parámetro on_select convierte el dataframe en un componente interactivo que permite al usuario seleccionar filas. Al seleccionar, se devuelve un objeto con los índices de las filas marcadas, lo que permite construir flujos donde la tabla actúa como filtro para otros componentes de la aplicación:
import streamlit as st
import pandas as pd
df = pd.DataFrame({
"nombre": ["Ana García", "Luis Martín", "María López", "Carlos Ruiz"],
"departamento": ["Ventas", "IT", "RRHH", "Marketing"],
"salario": [45000, 62000, 38000, 51000]
})
evento = st.dataframe(
df,
use_container_width=True,
hide_index=True,
on_select="rerun", # "ignore" (por defecto) o "rerun"
selection_mode="multi-row" # "single-row", "multi-row", "single-column", "multi-column"
)
if evento.selection.rows:
filas_sel = df.iloc[evento.selection.rows]
st.write(f"**{len(filas_sel)} fila(s) seleccionada(s):**")
st.dataframe(filas_sel, hide_index=True)
st.metric("Salario medio de la selección", f"€ {filas_sel['salario'].mean():,.0f}")
Resaltado de celdas con Pandas Styler
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(5, 4), columns=["A", "B", "C", "D"])
def color_negativo(val):
color = "#FFCCCC" if val < 0 else "#CCFFCC"
return f"background-color: {color}"
styled = df.style.applymap(color_negativo).format("{:.3f}")
st.dataframe(styled, use_container_width=True)
Columnas ocultas y orden de columnas
import streamlit as st
import pandas as pd
df = pd.DataFrame({
"id": range(1, 6),
"nombre": ["Ana", "Luis", "María", "Carlos", "Elena"],
"interno_id": ["INT001", "INT002", "INT003", "INT004", "INT005"], # No mostrar
"ventas": [45000, 62000, 38000, 51000, 29000]
})
st.dataframe(
df,
use_container_width=True,
hide_index=True,
column_order=["nombre", "ventas"], # Solo mostrar estas columnas en este orden
column_config={
"nombre": st.column_config.TextColumn("Vendedor"),
"ventas": st.column_config.NumberColumn("Ventas anuales", format="€%,.0f")
}
)
Contexto: el componente estrella para datos tabulares
st.dataframe es, probablemente, el componente más usado en aplicaciones Streamlit orientadas a ciencia de datos. A diferencia de st.table, que renderiza una tabla HTML estática, st.dataframe genera una tabla interactiva con virtualización de filas: solo se pintan las filas visibles en pantalla, lo que permite mostrar datasets de cientos de miles de filas sin bloquear el navegador.
Por debajo, el componente usa glide-data-grid, la misma biblioteca que impulsa notebooks como Observable y herramientas de BI modernas. Esto le da soporte nativo para ordenación por columna al hacer clic en el encabezado, búsqueda rápida con Ctrl+F, redimensionado de columnas arrastrando los separadores, y selección de celdas con arrastre del ratón. Todas estas interacciones se obtienen gratis sin añadir una sola línea de código.
Explicación línea por línea del ejemplo con column_config
- Se crea un DataFrame con columnas de distintos tipos: texto, email, número, progreso, booleano, fecha y URL.
column_configmapea cada columna a un tipo específico de renderizado.NumberColumnconformat="€%,.0f"muestra el salario con separador de miles, símbolo de euro y sin decimales.ProgressColumnconformat="%.0f%%"dibuja una barra de progreso dentro de la celda y muestra el porcentaje encima.CheckboxColumnrenderizaTrue/Falsecomo una casilla real (visualmente, aunque no editable enst.dataframe).DateColumnconformat="DD/MM/YYYY"convierte el string ISO a formato europeo legible.LinkColumncondisplay_text="Ver perfil"muestra texto personalizado en lugar de la URL cruda, haciéndola clicable.
Tabla completa de parámetros de st.dataframe
| Parámetro | Descripción |
|-----------|-------------|
| data | DataFrame, Series, Styler, numpy array o dict |
| width | Ancho en píxeles |
| height | Alto en píxeles |
| use_container_width | Ajusta al ancho del contenedor padre |
| hide_index | Oculta la columna de índice |
| column_order | Lista con el orden (y filtrado) de columnas |
| column_config | Diccionario con la configuración por columna |
| key | Identificador para sincronización con session_state |
| on_select | "ignore" o "rerun" para activar selección |
| selection_mode | "single-row", "multi-row", "single-column", "multi-column" |
Errores comunes
Datos con tipos incoherentes. Si una columna numérica contiene strings accidentales (por ejemplo, "N/A"), pandas la convierte a object y NumberColumn no puede aplicar el formato. Limpia con pd.to_numeric(col, errors="coerce") antes de pasarla al dataframe.
Ordenación por defecto que confunde. Los usuarios esperan que las tablas arranquen ordenadas por la primera columna, pero st.dataframe respeta el orden del DataFrame. Si necesitas un orden específico, aplica df.sort_values(...) antes de pasarlo al componente.
Selección que no rerun. Si usas on_select="rerun" pero accedes a evento.selection.rows antes del widget, obtendrás un error. La variable devuelta por st.dataframe(...) debe asignarse primero y usarse después.
Styler con muchas reglas. Los estilos aplicados con Pandas Styler se convierten a CSS inline, lo que puede ralentizar el renderizado en tablas muy grandes. Limita los estilos a columnas críticas y usa column_config siempre que sea posible.
Formatos numéricos con porcentajes. Para mostrar 0.87 como 87 % en NumberColumn, usa format="%.0f%%" y multiplica el valor por 100. Para ProgressColumn, los valores deben estar en el rango min_value/max_value especificado.
Mejores prácticas
- Usa siempre
hide_index=Truesalvo que el índice aporte información al usuario (series temporales con fechas). - Limita la altura con
heightpara evitar que tablas largas expandan la página y obliguen al usuario a hacer scroll. - Para datasets de más de 10 000 filas, considera paginar o aplicar filtros previos: aunque el componente virtualice, los datos se envían íntegros al navegador.
- Combina
ProgressColumncon una columna de texto para mostrar valores absolutos junto al indicador visual. - Usa
column_orderpara reordenar y ocultar columnas sin modificar el DataFrame original, manteniendo la lógica del dashboard separada de la estructura de datos. - Para exportar los datos mostrados, añade un
st.download_buttonque genere un CSV del DataFrame filtrado.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Streamlit es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Streamlit
Explora más contenido relacionado con Streamlit y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Renderizar DataFrames interactivos con st.dataframe y sus opciones de visualización. Personalizar el tipo y formato de cada columna con st.column_config. Habilitar la selección de filas con on_select para interactividad avanzada. Ocultar columnas, fijar el índice y controlar el ancho con parámetros de st.dataframe. Resaltar valores con estilos de Pandas antes de pasarlos a st.dataframe.