es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo hacer un diagrama de Sankey con Plotly con una capa que solo se extienda a un nivel?

Quiero crear un diagrama de Sankey que se divida en diferentes niveles (obviamente), pero uno de estos niveles debería detenerse después de uno, ya que los pasos siguientes no se aplican. Algo así como esto:

import pandas as pd

pd.DataFrame({
    'kind': ['no es un animal', 'animal', 'animal', 'animal', 'animal'],
    'animal': ['?', 'gato', 'gato', 'perro', 'gato'],
    'sex': ['?', 'hembra', 'hembra', 'macho', 'macho'],
    'status': ['?', 'domesticado', 'domesticado', 'salvaje', 'domesticado'],
    'count': [8, 10, 11, 14, 6]
})

La categoría 'no es un animal' no debería dividirse en niveles posteriores ya que no se aplican. Debería lucir así:

     kind             animal       sex          status          count
0   no es un animal       ?         ?            ?           8
1   animal              gato     hembra   domesticado    10
2   animal              gato     hembra   domesticado    11
3   animal              perro    macho    salvaje        14
4   animal              gato     macho    domesticado     6

El texto 'No es un animal' no debería dividirse en niveles posteriores ya que no se aplican. Debería lucir así:

image enlace

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para crear un diagrama de Sankey que se detenga después de cierto nivel, puedes usar el atributo visible de los objetos node y link en go.Sankey de plotly.graph_objs. El atributo visible te permite mostrar u ocultar selectivamente un nodo o enlace en particular en base a una condición.

    Por ejemplo, supongamos que tienes un DataFrame como el que se encuentra en la pregunta:

    import pandas as pd
    
    df = pd.DataFrame({
        'kind': ['no es un animal', 'animal', 'animal', 'animal', 'animal'],
        'animal': ['?', 'gato', 'gato', 'perro', 'gato'],
        'sexo': ['?', 'hembra', 'hembra', 'macho', 'macho'],
        'estado': ['?', 'domesticado', 'domesticado', 'salvaje', 'domesticado'],
        'cantidad': [8, 10, 11, 14, 6]
    })
    

    Para crear un diagrama de Sankey que se detenga en el nivel de kind para “no es un animal”, puedes inicializar listas vacías para los nodos y enlaces, y luego usar un bucle para agregar nodos y enlaces en base a las columnas kind, animal, sexo y estado:

    import plotly.graph_objs as go
    
    nodos = []
    enlaces = []
    
    # bucle sobre cada fila en el DataFrame
    for i, fila in df.iterrows():
    
        # agregar nodo para la columna kind
        nodo_desde = fila['kind']
        if nodo_desde not in nodos:
            nodos.append(nodo_desde)
    
        # condición para detener la adición de nodos y enlaces después de "no es un animal"
        if nodo_desde == 'no es un animal':
            continue
    
        # agregar nodo para la columna animal
        nodo_a = f"{fila['kind']}_{fila['animal']}"
        if nodo_a not in nodos:
            nodos.append(nodo_a)
    
        # agregar enlace desde la columna kind hasta la columna animal
        enlaces.append(dict(
            source=nodo_desde,
            target=nodo_a,
            value=fila['cantidad']
        ))
    
        # agregar nodo para la columna sexo
        nodo_desde = nodo_a
        nodo_a = f"{nodo_a}_{fila['sexo']}"
        if nodo_a not in nodos:
            nodos.append(nodo_a)
    
        # agregar enlace desde la columna animal hasta la columna sexo
        enlaces.append(dict(
            source=nodo_desde,
            target=nodo_a,
            value=fila['cantidad']
        ))
    
        # agregar nodo para la columna estado
        nodo_desde = nodo_a
        nodo_a = f"{nodo_a}_{fila['estado']}"
        if nodo_a not in nodos:
            nodos.append(nodo_a)
    
        # agregar enlace desde la columna sexo hasta la columna estado
        enlaces.append(dict(
            source=nodo_desde,
            target=nodo_a,
            value=fila['cantidad']
        ))
    
        # fin del bucle sobre las filas
    
    # crear el diagrama de Sankey utilizando los nodos y enlaces
    figura = go.Figure(data=[go.Sankey(
        node=dict(
            pad=10,
            thickness=20,
            line=dict(color="black", width=0.5),
            label=nodos,
            # establecer el atributo visible en base a una condición (detener en el nivel de "no es un animal")
            visible=[True if n != 'no es un animal' else False for n in nodos]
        ),
        link=dict(
            source=[enlace['source'] for enlace in enlaces],
            target=[enlace['target'] for enlace in enlaces],
            value=[enlace['value'] for enlace in enlaces],
        ))])
    
    figura.show()
    

    El código utiliza concatenación de cadenas para crear etiquetas de nodos únicas para cada combinación de kind, animal, sexo y estado. También establece el atributo visible de cada nodo en base a una condición: si el nodo representa “no es un animal”, su atributo visible se establece en False. Esto garantiza que el diagrama de Sankey se detenga después del nivel de kind para “no es un animal” y no muestre niveles posteriores.

    El diagrama de Sankey resultante debería verse como la imagen de la pregunta.

Comments are closed.