Crea un panel de control utilizando Python y Dash

Crea un panel de control con Python y Dash

 

Introducción

 

En el ámbito de la ciencia de datos y el análisis, el poder de los datos se libera no solo extrayendo ideas sino también comunicando efectivamente estas ideas; aquí es donde entra en juego la visualización de datos.

   

La visualización de datos es una representación gráfica de información y datos. Utiliza elementos visuales como gráficos y mapas, lo que facilita ver patrones, tendencias y valores atípicos en los datos sin procesar. Para los científicos de datos y analistas, la visualización de datos es una herramienta esencial que facilita una comprensión más rápida y precisa de los datos, apoya la narración con datos y ayuda a tomar decisiones basadas en datos.

En este artículo, aprenderás a utilizar Python y el marco de trabajo Dash para crear un panel de control para visualizar la distribución y clasificación del contenido de Netflix.

   

¿Qué es Dash?

 

Dash es un marco de trabajo de código bajo de código abierto desarrollado por Plotly para crear aplicaciones web analíticas en Python puro. Tradicionalmente, para este tipo de aplicaciones, uno podría necesitar utilizar JavaScript y HTML, lo que requeriría tener experiencia en tecnologías de backend (Python) y frontend (JavaScript, HTML).

Sin embargo, Dash cubre esta brecha, permitiendo a los científicos de datos y analistas construir paneles interactivos y estéticos utilizando solo Python. Este aspecto de desarrollo de bajo código hace que Dash sea una elección adecuada para crear paneles analíticos, especialmente para aquellos que se sienten más cómodos con Python.

 

Análisis del conjunto de datos

 

Ahora que te has familiarizado con Dash, comencemos nuestro proyecto práctico. Utilizarás el conjunto de datos de películas y programas de televisión de Netflix disponible en Kaggle, creado por Shivam Bansal.

Este conjunto de datos incluye detalles sobre las películas y programas de televisión disponibles en Netflix hasta 2021, como el tipo de contenido, título, director, reparto, país de producción, año de lanzamiento, clasificación, duración y más.

Aunque el conjunto de datos se creó en 2021, sigue siendo un recurso valioso para desarrollar habilidades de visualización de datos y comprender las tendencias en el entretenimiento mediático.

Utilizando este conjunto de datos, el objetivo será crear un panel de control que permita visualizar los siguientes puntos:

  1. Distribución geográfica del contenido: Un gráfico de mapa que muestra cómo varía la producción de contenido en diferentes países a lo largo de los años.
  2. Clasificación del contenido: Esta visualización divide el contenido de Netflix en programas de televisión y películas para ver qué géneros son más prominentes.

 

Configuración del espacio de trabajo del proyecto

 

Comencemos creando un directorio para el proyecto llamado netflix-dashboard, luego inicializa y activa un entorno virtual de Python mediante los siguientes comandos:

# Linux y MacOS
mkdir netflix-dashboard && cd netflix-dashboard
python3 -m venv netflix-venv && source netflix-venv/bin/activate

 

# Windows Powershell
mkdir netflix-dashboard && cd netflix-dashboard
python -m venv netflix-venv && .\netflix-venv\Scripts\activate

 

A continuación, deberás instalar algunos paquetes externos. Utilizarás pandas para la manipulación de datos, dash para crear el panel de control, plotly para crear los gráficos y dash-bootstrap-components para agregar estilo al panel de control:

# Linux y MacOS
pip3 install pandas dash plotly dash-bootstrap-components

 

# Windows Powershell
pip install pandas dash plotly dash-bootstrap-components

 

Limpiando el conjunto de datos

 

Al revisar el conjunto de datos de Netflix, encontrarás valores faltantes en las columnas de directorcast y country. También sería conveniente convertir los valores de la columna date_added de tipo string a tipo datetime para un análisis más sencillo.

Para limpiar el conjunto de datos, puedes crear un nuevo archivo clean_netflix_dataset.py, con el siguiente código y luego ejecutarlo:

import pandas as pd

# Cargar el conjunto de datos
df = pd.read_csv('netflix_titles.csv')

# Rellenar valores faltantes
df['director'].fillna('Sin director', inplace=True)
df['cast'].fillna('Sin reparto', inplace=True)
df['country'].fillna('Sin país', inplace=True)

# Eliminar valores faltantes y duplicados
df.dropna(inplace=True)
df.drop_duplicates(inplace=True)

# Eliminar espacios en blanco de la columna `date_added` y convertir valores a `datetime`
df['date_added'] = pd.to_datetime(df['date_added'].str.strip())

# Guardar el conjunto de datos limpio
df.to_csv('netflix_titles.csv', index=False)

 

Empezando con Dash

 

Con el entorno configurado y el conjunto de datos limpio, estás listo para empezar a trabajar en tu panel de control. Crea un nuevo archivo app.py, con el siguiente código:

from dash import Dash, dash_table, html
import pandas as pd

# Inicializar una aplicación Dash
app = Dash(__name__)

# Definir el diseño de la aplicación
app.layout = html.Div([
        html.H1('Panel de Películas y Programas de TV de Netflix'),
        html.Hr(),
])

# Iniciar la aplicación Dash en modo de desarrollo local
if __name__ == '__main__':
    app.run_server(debug=True)

 

Veamos el código dentro de app.py:

  • app = Dash(__name__): Esta línea inicializa una nueva aplicación Dash. Piensa en ella como la base de tu aplicación.
  • app.layout = html.Div(…): El atributo app.layout te permite escribir código similar a HTML para diseñar la interfaz de usuario de tu aplicación. El diseño anterior utiliza un elemento de encabezado html.H1(…) para el título del panel y un elemento de línea horizontal html.Hr() debajo del título.
  • app.run(debug=True): Esta línea inicia un servidor de desarrollo que sirve tu aplicación Dash en modo de desarrollo local. Dash utiliza Flask, un marco de servidor web ligero, para servir tus aplicaciones a los navegadores web.

Después de ejecutar app.py, verás un mensaje en tu terminal que indica que tu aplicación Dash se está ejecutando y está accesible en http://127.0.0.1:8050/. Abre esta URL en tu navegador web para verla:

   

¿El resultado se ve muy simple, verdad? ¡No te preocupes! Esta sección tiene como objetivo mostrar la estructura y componentes más básicos de una aplicación Dash. ¡Pronto agregarás más características y componentes para convertirlo en un panel de control increíble!

 

Incorporando componentes de Dash Bootstrap

 

El siguiente paso es escribir el código para el diseño de tu panel de control y añadirle estilo. Para esto, puedes usar Dash Bootstrap Components (DBC), una biblioteca que proporciona componentes de Bootstrap para Dash, lo que te permite desarrollar aplicaciones con estilo y diseños responsivos.

El panel de control tendrá un estilo de diseño de pestañas, que proporciona una forma compacta de organizar diferentes tipos de información dentro del mismo espacio. Cada pestaña corresponderá a una visualización distinta.

Adelante, modifica el contenido de app.py para incorporar DBC:

from dash import Dash,dcc, html
import pandas as pd
import dash_bootstrap_components as dbc

# Inicializar la aplicación Dash e importar el tema de Bootstrap para darle estilo al panel de control
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container(
    [
        dcc.Store(id='store'),
        html.H1('Panel de Películas y Programas de TV de Netflix'),
        html.Hr(),
        dbc.Tabs(
            [
                dbc.Tab(label='Distribución geográfica de contenido', tab_id='tab1'),
                dbc.Tab(label='Clasificación de contenido', tab_id='tab2'),
            ],
            id='tabs',
            active_tab='tab1',
        ),
        html.Div(id='tab-content', className='p-4'),
    ]
)

if __name__ == '__main__':
    app.run(debug=True)

 

En este diseño modificado, verás nuevos componentes:

  • dbc.Container: Usando dbc.Container como el componente de nivel superior, envuelve todo el diseño del panel de control en un contenedor receptivo y flexible.
  • dcc.Store: Este componente principal de Dash te permite almacenar datos en el lado del cliente (en el navegador del usuario), mejorando el rendimiento de la aplicación al mantener los datos localmente.
  • dbc.Tabs y dbc.Tab: Cada dbc.Tab representa una pestaña individual que contendrá diferentes visualizaciones. La propiedad label es lo que aparece en la pestaña misma, y tab_id se utiliza para identificar la pestaña. La propiedad active_tab de dbc.Tabs se utiliza para especificar la pestaña activa cuando la aplicación Dash se inicia.

Ahora ejecuta app.py. El panel de control resultante tendrá un diseño con estilo Bootstrap con dos pestañas vacías:

   

¡Buen trabajo! Finalmente estás listo para agregar visualizaciones al panel de control.

 

Agregando Callbacks y Visualizaciones

 

Cuando trabajas con Dash, la interactividad se logra a través defunciones de callback. Una función de callback es una función que se llama automáticamente cuando cambia una propiedad de entrada. Se llama “callback” porque es una función que es “llamada de vuelta” por Dash cada vez que ocurre un cambio en la aplicación.

En este panel de control, utilizarás callbacks para mostrar la visualización relevante en la pestaña seleccionada, y cada visualización se almacenará en su propio archivo Python dentro de un nuevo directorio llamado components para una mejor organización y modularidad de la estructura del proyecto.

 

Visualización de la distribución geográfica del contenido

 

Creemos un nuevo directorio llamado components, y dentro de él, creemos el archivo geographical_content.py que generará un mapa coroplético que ilustra cómo varía la producción de contenido de Netflix por país a lo largo de los años:

import pandas as pd
import plotly.express as px
from dash import dcc, html

df = pd.read_csv('netflix_titles.csv')

# Filtrar las entradas sin información de país y, si hay varios países de producción,
# considerar el primero como el país de producción
df['country'] = df['country'].str.split(',').apply(lambda x: x[0].strip() if isinstance(x, list) else None)

# Extraer el año de la columna date_added
df['year_added'] = pd.to_datetime(df['date_added']).dt.year
df = df.dropna(subset=['country', 'year_added'])

# Calcular la cantidad de contenido producido por cada país para cada año
df_counts = df.groupby(['country', 'year_added']).size().reset_index(name='count')

# Ordenar el DataFrame por 'year_added' para asegurar que los fotogramas de animación estén en orden ascendente
df_counts = df_counts.sort_values('year_added')

# Crear el mapa coroplético con un control deslizante para el año
fig1 = px.choropleth(df_counts,
                     locations='country',
                     locationmode='country names',
                     color='count',
                     hover_name='country',
                     animation_frame='year_added',
                     projection='natural earth',
                     title='Contenido producido por países a lo largo de los años',
                     color_continuous_scale='YlGnBu',
                     range_color=[0, df_counts['count'].max()])
fig1.update_layout(width=1280, height=720, title_x=0.5)

# Calcular la cantidad de contenido producido para cada año por tipo y rellenar ceros para los pares tipo-año faltantes
df_year_counts = df.groupby(['year_added', 'type']).size().reset_index(name='count')

# Crear el gráfico de líneas utilizando plotly express
fig2 = px.line(df_year_counts, x='year_added', y='count', color='type',
               title='Distribución de contenido por tipo a lo largo de los años',
               markers=True, color_discrete_map={'Movie': 'dodgerblue', 'TV Show': 'darkblue'})
fig2.update_traces(marker=dict(size=12))
fig2.update_layout(width=1280, height=720, title_x=0.5)

layout = html.Div([
    dcc.Graph(figure=fig1),
    html.Hr(),
    dcc.Graph(figure=fig2)
])

 

El código anterior filtra y agrupa los datos por ‘country’ y ‘year_added’, luego calcula el conteo de contenido producido por cada país para cada año dentro del DataFrame df_counts.

Luego, la función px.choropleth construye el gráfico del mapa utilizando las columnas del DataFrame df_counts como valores para sus argumentos:

  • locations=’country’: Te permite especificar los valores de ubicación geográfica contenidos en la columna ‘country’.
  • locationmode=’country names’: Este argumento “le dice a la función” que las ubicaciones proporcionadas son nombres de países, ya que Plotly Express también admite otros modos de ubicación como códigos de país ISO-3 o estados de EE. UU.
  • color=’count’: Se utiliza para especificar los datos numéricos utilizados para colorear el mapa. Aquí, se refiere a la columna ‘count’, que contiene el conteo de contenido producido por cada país para cada año.
  • color_continuous_scale=’YlGnBu’: Construye una escala de color continua para cada país en el mapa cuando la columna denotada por color contiene datos numéricos.
  • animation_frame=’year_added’: Este argumento crea una animación sobre la columna ‘year_added’. Agrega un control deslizante de años al gráfico del mapa, lo que te permite ver una animación que representa la evolución de esta producción de contenido en cada país año tras año.
  • projection=’natural earth’: Este argumento no utiliza ninguna columna del DataFrame df_counts; sin embargo, se requiere el valor ‘natural earth’ para establecer la proyección con el mapa mundial de la Tierra.

Y justo debajo del mapa coroplético, se incluye un gráfico de línea con marcadores que muestra el cambio en el volumen de contenido, categorizado por tipo (programas de TV o películas), a lo largo de los años.

Para generar el gráfico de línea, se crea un nuevo DataFrame df_year_counts, que agrupa los datos originales df por las columnas ‘year_added’ y ‘type’, contabilizando el conteo de contenido para cada combinación.

Estos datos agrupados se utilizan luego con px.line, donde los argumentos ‘x’ e ‘y’ se asignan a las columnas ‘year_added’ y ‘count’ respectivamente, y el argumento ‘color’ se establece en ‘type’ para diferenciar entre programas de TV y películas.

 

Visualización de clasificación de contenido

 

El siguiente paso es crear un nuevo archivo llamado content_classification.py, que generará un gráfico de treemap para visualizar el contenido de Netflix desde una perspectiva de tipo y género:

import pandas as pd
import plotly.express as px
from dash import dcc, html

df = pd.read_csv('netflix_titles.csv')

# Dividir la columna 'listed_in' y explotar para manejar varios géneros
df['listed_in'] = df['listed_in'].str.split(', ')
df = df.explode('listed_in')

# Calcular el conteo de cada combinación de tipo y género
df_counts = df.groupby(['type', 'listed_in']).size().reset_index(name='count')

fig = px.treemap(df_counts, path=['type', 'listed_in'], values='count', color='count',
                 color_continuous_scale='Ice', title='Contenido por tipo y género')

fig.update_layout(width=1280, height=960, title_x=0.5)
fig.update_traces(textinfo='label+percent entry', textfont_size=14)

layout = html.Div([
    dcc.Graph(figure=fig),
])

 

En el código anterior, después de cargar los datos, se ajusta la columna ‘listed_in’ para manejar varios géneros por contenido dividiéndolos y explotando los géneros, creando una nueva fila para cada género por contenido.

Luego, se crea el DataFrame df_counts para agrupar los datos por las columnas ‘type’ y ‘listed_in’, y calcular el conteo de cada combinación de tipo y género.

Luego, las columnas del DataFrame df_counts se utilizan como valores para los argumentos de la función px.treemap de la siguiente manera:

  • path=['type', 'listed_in']: Estas son las categorías jerárquicas representadas en el treemap. Las columnas 'type' y 'listed_in' contienen los tipos de contenido (programas de TV o películas) y los géneros, respectivamente.
  • values='count': El tamaño de cada rectángulo en el treemap corresponde a la columna 'count', que representa la cantidad de contenido para cada combinación tipo-género.
  • color='count': La columna 'count' también se utiliza para colorear los rectángulos en el treemap.
  • color_continous_scale='Ice': Construye una escala de colores continuos para cada rectángulo en el treemap cuando la columna indicada por color contiene datos numéricos.

Después de crear los dos nuevos archivos de visualización, así es como debería verse la estructura actual de tu proyecto:

netflix-dashboard
├── app.py
├── clean_netflix_dataset.py
├── components
│   ├── content_classification.py
│   └── geographical_content.py
├── netflix-venv
│   ├── bin
│   ├── etc
│   ├── include
│   ├── lib
│   ├── pyvenv.cfg
│   └── share
└── netflix_titles.csv

 

Implementando callbacks

 

El último paso es modificar app.py para importar las dos nuevas visualizaciones dentro del directorio components e implementar funciones de callback para renderizar los gráficos al seleccionar las pestañas:

from dash import Dash, dcc, html, Input, Output
import dash_bootstrap_components as dbc
from components import (
    geographical_content,
    content_classification
)

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container(
    [
        dcc.Store(id='store'),
        html.H1('Netflix Movies and TV Shows Dashboard'),
        html.Hr(),
        dbc.Tabs(
            [
                dbc.Tab(label='Distribución geográfica del contenido', tab_id='tab1'),
                dbc.Tab(label='Clasificación del contenido', tab_id='tab2'),
            ],
            id='tabs',
            active_tab='tab1',
        ),
        html.Div(id='tab-content', className='p-4'),
    ]
)


# Esta función de callback cambia entre pestañas en un panel de control según la selección del usuario.
# Actualiza el componente 'tab-content' con el diseño de la nueva pestaña seleccionada.
@app.callback(Output('tab-content', 'children'), [Input('tabs', 'active_tab')])
def switch_tab(at):
    if at == 'tab1':
        return geographical_content.layout
    elif at == 'tab2':
        return content_classification.layout


if __name__ == '__main__':
    app.run(debug=True)

 

El decorador de la función de callback @app.callback escucha los cambios en la propiedad 'active_tab' del componente 'tabs', representado por el objeto Input.

Cada vez que cambia la propiedad 'active_tab', se activa la función switch_tab. Esta función verifica la identificación 'active_tab' y devuelve el diseño correspondiente para ser renderizado en el Div 'tab-content', como indica el objeto Output. Por lo tanto, al cambiar de pestaña, aparece la visualización relevante.

Finalmente, ejecuta app.py nuevamente para ver el panel de control actualizado con las nuevas visualizaciones:

   

Conclusión

 

Este artículo te enseñó cómo crear un panel de control para explorar y visualizar la distribución y clasificación del contenido de Netflix. Al aprovechar el poder de Python y Dash, ahora estás equipado para crear tus propias visualizaciones, proporcionando información valiosa sobre tus datos.

Puedes ver todo el código de este proyecto en el siguiente repositorio de GitHub: https://github.com/gutyoh/netflix-dashboard

Si encontraste este artículo útil y quieres ampliar tus conocimientos sobre Python y Ciencia de Datos, considera echar un vistazo a la Introducción a la trayectoria de Ciencia de Datos en Hyperskill.

Hazme saber en los comentarios a continuación si tienes alguna pregunta o comentario sobre este blog.

Hermann Rösch es un Autor Técnico para la trayectoria de programación en Go en Hyperskill, donde combino mi pasión por la Tecnología Educativa para empoderar a la próxima generación de ingenieros de software. Al mismo tiempo, adentrándome en el mundo de los datos como estudiante de maestría en la Universidad de Illinois en Urbana-Champaign.

Original. Repostead con permiso.

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

Barry Diller vs. IA Generativa Batalla Legal de Derechos de Autor

El magnate de los medios de comunicación Barry Diller y un grupo de destacados editores se están preparando para una ...

Aprendizaje Automático

AI Ve lo que tú Ves Mind's Eye es un Modelo de IA que Puede Reconstruir Escaneos Cerebrales en Imágenes.

Desde hace tiempo, nos ha intrigado el desafío de entender cómo funciona nuestro cerebro. El campo de la neurociencia...

Aprendizaje Automático

Redes Neuronales con Paso de Mensajes Retrasado y Reconfiguración Dinámica

Esta publicación fue coescrita con Francesco Di Giovanni y Ben Gutteridge y se basa en el artículo de B. Gutteridge e...

Inteligencia Artificial

EE. UU. y la UE completan el tan esperado acuerdo sobre el intercambio de datos

El acuerdo pone fin a la incertidumbre legal para Meta, Google y decenas de empresas, al menos por ahora.

Inteligencia Artificial

Una Bendición y un Monstruo Los Anunciantes Aceptan Cautelosamente la Inteligencia Artificial

Muchos anuncios son más fáciles de hacer con la tecnología en constante mejora. También representa una amenaza para u...

Aprendizaje Automático

Toma esto y conviértelo en una marioneta digital GenMM es un modelo de IA que puede sintetizar movimiento usando un solo ejemplo.

Las animaciones generadas por computadora se están volviendo cada vez más realistas cada día. Este avance se puede ve...