Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

164
Visualizações
Bokeh Networkx graph slider not updating correctly

Here is a minimal working example for the problem I am facing:

I am building a simple graph with Networkx and then displaying it with Bokeh, adding a slider to show only the edges whose weight is greater than the slider value. Unfortunately, this works perfectly when the value increases, i.e., the slider moves to the right, whereas it stops working (some edges reappear, but then, when clicking on the graph, everything blows up) when the slider value decreases. In the customJS callback function I am modifying the edge data, and also when printing to the console every part of it, they work as expected, but in browser console I get a Shape Mismatch error, even if it is not specified what two shapes are being compared.

import pandas as pd
import networkx as nx
from bokeh.io import show 
from bokeh.plotting import figure, from_networkx
from bokeh.models import CustomJS, Slider
from bokeh.layouts import row, column
import copy

df = pd.DataFrame(data={'Source': {0: 'A', 1: 'A', 2: 'A', 3: 'B', 4: 'B', 5: 'C'},
                        'Target': {0: 'B', 1: 'C', 2: 'D', 3: 'C', 4: 'D', 5: 'D'},
                        'Weight': {0: 0, 1: 1, 2: 1.5, 3: 0.6, 4: 3, 5: 4}}) 

G = nx.from_pandas_edgelist(df, 'Source', 'Target', 'Weight')

plot = figure(title='Attempt')
network_graph = from_networkx(G, nx.circular_layout, scale=1, center=(0, 0))
plot.renderers.append(network_graph)

# save edge data to select only a subset of the edges
backup_edge_data = copy.deepcopy(network_graph.edge_renderer.data_source.data)

slider = Slider(start=0, end=4, value=0, step=.2)


# the last line of this object (the one with change.emit()) is probably unnecessary
code = """
const old_Weight = edata["Weight"];
const old_start = edata["start"];
const old_end = edata["end"];

let acceptableIndexes = old_Weight.reduce(function(acc, curr, index) {
  if (curr >= cb_obj.value) {
    acc.push(index);
  }
  return acc;
}, []);


const new_Weight = acceptableIndexes.map(i => old_Weight[i]);
const new_start = acceptableIndexes.map(i => old_start[i]);
const new_end = acceptableIndexes.map(i => old_end[i]);

const new_data_edge = {'Weight': new_Weight, 
                       'start': new_start, 
                       'end': new_end};

graph_setup.edge_renderer.data_source.data = new_data_edge; 
graph_setup.edge_renderer.data_source.change.emit();
"""

callback = CustomJS(args = dict(graph_setup = network_graph,
                                edata = backup_edge_data),
                    code = code)

slider.js_on_change('value', callback)

layout = row(
    plot,
    column(slider),
)

show(layout)

image of the networkx graph and the slider

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

I found out that this is actually due to a bug: https://discourse.bokeh.org/t/dynamic-layout-behavior-changes-between-bokeh-2-2-3-and-bokeh-2-3-0/7594

To solve this until the bokeh library is not updated (I am using version 2.4.0) I modified the customJS code to add placeholder data to match the initial datasource dimension:

code = """
const old_Weight = edata["Weight"];
const old_start = edata["start"];
const old_end = edata["end"];

let acceptableIndexes = old_Weight.reduce(function(acc, curr, index) {
  if (curr >= cb_obj.value) {
    acc.push(index);
  }
  return acc;
}, []);

\\ compute how many fake edges have to be added
const num_ph = old_Weight.length - acceptableIndexes.length
\\ create an array of that dimension with fake value '9999'
const placeholder = Array(num_ph).fill('9999')

\\ for each new value, concatenate the new array with the placeholder array
const new_Weight = acceptableIndexes.map(i => old_Weight[i]).concat(placeholder);
const new_start = acceptableIndexes.map(i => old_start[i]).concat(placeholder);
const new_end = acceptableIndexes.map(i => old_end[i]).concat(placeholder);

const new_data_edge = {'Weight': new_Weight, 
                       'start': new_start, 
                       'end': new_end};

graph_setup.edge_renderer.data_source.data = new_data_edge; 
graph_setup.edge_renderer.data_source.change.emit();
"""
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda