плотное графическое форматирование данных

#python #dataframe #plotly #sankey-diagram

Вопрос:

в библиотеке plotly есть несколько хороших диаграмм сэнки https://plotly.com/python/sankey-diagram/

но данные требуют, чтобы вы передавали индексы пар источник/цель.

     link = dict(
      source = [0, 1, 0, 2, 3, 3], # indices correspond to labels, eg A1, A2, A1, B1, ...
      target = [2, 3, 3, 4, 4, 5],
 

Мне было интересно, есть ли API для простой передачи именованного списка этих пар?

 links = [
    {'source': 'start', 'target': 'A', 'value': 2},
    {'source': 'A', 'target': 'B', 'value': 2},
...
]
 

это больше соответствует тому, как боке/голографические изображения
ожидает данных (но этот сэнки не работает с самоциклами)

а также этот виджет писанки

чтобы я мог приблизиться к своему фрейму данных, не обрабатывая все?

или есть хороший питонический способ преобразовать это в одну строку 😀

Ответ №1:

  • структура явно представляет собой формат конструктора фреймов данных pandas
  • создайте из него фрейм данных плюс серию ключей узлов
  • исходя из этого, из этого просто построить Сэнки-сюжет
 import pandas as pd
import numpy as np
import plotly.graph_objects as go

links = [
    {'source': 'start', 'target': 'A', 'value': 2},
    {'source': 'A', 'target': 'B', 'value': 1},
    {'source': 'A', 'target':'C', 'value':.5}

]

df = pd.DataFrame(links)
nodes = np.unique(df[["source","target"]], axis=None)
nodes = pd.Series(index=nodes, data=range(len(nodes)))

go.Figure(
    go.Sankey(
        node={"label": nodes.index},
        link={
            "source": nodes.loc[df["source"]],
            "target": nodes.loc[df["target"]],
            "value": df["value"],
        },
    )
)

 

введите описание изображения здесь

Комментарии:

1. мило! итак, вы бы предпочли nodes = np.unique(df.loc[:,["source","target"]].values.ravel()) что-то вроде понимания списка на клавишах? мне немного трудно читать с [:, помощью «и ravel «… но у меня нет более простой альтернативы.

2. numpy.org/doc/stable/reference/generated/… сделал бы то же самое. Я довольно давно работаю с пандами и numpy, поэтому мне комфортно с идиомами… 🙂 может быть, это более читабельно np.unique(df[["source","target"]].values.flatten()) для удобства чтения

3. nodes = np.unique(df[["source","target"]], axis=None) еще более лаконично …

4. намного приятнее, спасибо! вы хотите отредактировать свой ответ? я все равно согласился