如何向Plotly图的节点添加自定义值

huangapple go评论71阅读模式
英文:

How to add custom values to nodes of plotly graph

问题

var values = nodes[nodeIndex].value; 无法访问节点值。

建议如何修复此问题将非常有帮助。

英文:

I'm trying to add values to nodes of plotly graph but there is an issue.

Code:

<html>
  <head>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <style>
      .graph-container {
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .main-panel {
        width: 70%;
        float: left;
      }

      .side-panel {
        width: 30%;
        background-color: lightgray;
        min-height: 300px;
        overflow: auto;
        float: right;
      }
    </style>
  </head>
  <body>
    <div class="graph-container">
      <div id="myDiv" class="main-panel"></div>
      <div id="lineGraph" class="side-panel"></div>
    </div>
    <script>
      var nodes = [
        { x: 0, y: 0, z: 0, value: [1, 2, 3] },
        { x: 1, y: 1, z: 1, value: [4, 5, 6] },
        { x: 2, y: 0, z: 2, value: [7, 8, 9] },
        { x: 3, y: 1, z: 3, value: [10, 11, 12] },
        { x: 4, y: 0, z: 4, value: [13, 14, 15] }
      ];

      var edges = [
        { source: 0, target: 1 },
        { source: 1, target: 2 },
        { source: 2, target: 3 },
        { source: 3, target: 4 }
      ];

      var x = [];
      var y = [];
      var z = [];

      for (var i = 0; i < nodes.length; i++) {
        x.push(nodes[i].x);
        y.push(nodes[i].y);
        z.push(nodes[i].z);
      }

      var xS = [];
      var yS = [];
      var zS = [];
      var xT = [];
      var yT = [];
      var zT = [];

      for (var i = 0; i < edges.length; i++) {
        xS.push(nodes[edges[i].source].x);
        yS.push(nodes[edges[i].source].y);
        zS.push(nodes[edges[i].source].z);
        xT.push(nodes[edges[i].target].x);
        yT.push(nodes[edges[i].target].y);
        zT.push(nodes[edges[i].target].z);
      }

      var traceNodes = {
        x: x, y: y, z: z,
        mode: 'markers',
        marker: { size: 12, color: 'red' },
        type: 'scatter3d',
        text: [0, 1, 2, 3, 4],
        hoverinfo: 'text',
        hoverlabel: {
          bgcolor: 'white'
        },
        customdata: nodes.map(function(node) {
            if (node.value !== undefined)
               return node.value;
        }),
        type: 'scatter3d'
      };

      var layout = {
        margin: { l: 0, r: 0, b: 0, t: 0 }
      };

      Plotly.newPlot('myDiv', [traceNodes], layout, { displayModeBar: false });

      document.getElementById("myDiv").on("plotly_click", function(data){
      var nodeIndex = data.points[0].pointIndex;
      var values = nodes[nodeIndex].value;
      console.log(values);

      Plotly.newPlot('lineGraph', [{ x: [0, 1, 2], y: values, type: 'scatter3d'}], {
      margin: { t: 0 }
      });
      });
    </script>
   </body>
</html>

var values = nodes[nodeIndex].value; is not able to access the node values.

Suggestions on how to fix this will be really helpful.

EDIT0:

<html>
  <head>
    <script src="https://cdn.plot.ly/plotly-1.58.5.min.js"></script>
    <style>
      .graph-container {
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .main-panel {
        width: 70%;
        float: left;
      }

      .side-panel {
        width: 30%;
        background-color: lightgray;
        min-height: 300px;
        overflow: auto;
        float: right;
      }
    </style>
  </head>
  <body>
    <div class="graph-container">
      <div id="myDiv" class="main-panel"></div>
      <div id="lineGraph" class="side-panel"></div>
    </div>
    <script>
      var nodes = [
        { x: 0, y: 0, z: 0, value: [1, 2, 3] },
        { x: 1, y: 1, z: 1, value: [4, 5, 6] },
        { x: 2, y: 0, z: 2, value: [7, 8, 9] },
        { x: 3, y: 1, z: 3, value: [10, 11, 12] },
        { x: 4, y: 0, z: 4, value: [13, 14, 15] }
      ];

      var edges = [
        { source: 0, target: 1 },
        { source: 1, target: 2 },
        { source: 2, target: 3 },
        { source: 3, target: 4 }
      ];

      var x = [];
      var y = [];
      var z = [];

      for (var i = 0; i < nodes.length; i++) {
        x.push(nodes[i].x);
        y.push(nodes[i].y);
        z.push(nodes[i].z);
      }

      var xS = [];
      var yS = [];
      var zS = [];
      var xT = [];
      var yT = [];
      var zT = [];

      for (var i = 0; i < edges.length; i++) {
        xS.push(nodes[edges[i].source].x);
        yS.push(nodes[edges[i].source].y);
        zS.push(nodes[edges[i].source].z);
        xT.push(nodes[edges[i].target].x);
        yT.push(nodes[edges[i].target].y);
        zT.push(nodes[edges[i].target].z);
      }

      var traceNodes = {
        x: x, y: y, z: z,
        mode: 'markers',
        marker: { size: 12, color: 'red' },
        type: 'scatter3d',
        text: [0, 1, 2, 3, 4],
        hoverinfo: 'text',
        hoverlabel: {
          bgcolor: 'white'
        },
        customdata: nodes.map(function(node) {
            if (node.value !== undefined)
               return node.value;
        }),
        type: 'scatter3d'
      };

      var layout = {
        margin: { l: 0, r: 0, b: 0, t: 0 }
      };

      Plotly.newPlot('myDiv', [traceNodes], layout, { displayModeBar: false });
      const ymax = Math.max(...nodes.map(n => n.value).flat());

      document.getElementById("myDiv").on("plotly_click", function(data){
      var nodeIndex = data.points[0].pointNumber;
      var values = nodes[nodeIndex].value;
      console.log(values);

      Plotly.newPlot('lineGraph', [{ x: [0, 1, 2], y: values, type: 'scatter3d'}], {
      margin: { t: 0 },
      yaxis: {autorange: false, range: [0, ymax + 1]}
      });
      });
    </script>
   </body>
</html>

I made the corrections suggested in the answer below but the I am still not able to see the line graph when nodes in the main panel are clicked.

答案1

得分: 1

使用pointNumber代替pointIndex。同时,你需要修复第二个图的type,我建议设置一个固定的轴范围(否则轴会在每个选定的点上重置):

// 线图的最大y值
const ymax = Math.max(...nodes.map(n => n.value).flat());

document.getElementById('myDiv').on('plotly_click', function(data){
  var nodeIndex = data.points[0].pointNumber;
  var values = nodes[nodeIndex].value;

  Plotly.newPlot('lineGraph', [{
    type: 'scatter',
    mode: 'lines',
    x: [0, 1, 2],
    y: values
  }, {
    margin: { t: 0 },
    yaxis: {autorange: false, range: [0, ymax + 1]}
  }]);
});

作为参考,这是用于3D图的event data结构:

{
  points: [{
    curveNumber: 2,  // 与选定点关联的跟踪在数据中的索引
    pointNumber: 2,  // 选定点的索引
    x: 5,        // x值
    y: 600,      // y值
    z: 12,       // z值
    data: {/* */},       // 与选定点一起发送到Plotly.newPlot的跟踪的引用
    fullData: {/* */},   // 包含所有默认属性的跟踪的引用
   xaxis: {/* */},   // 与选定点关联的x轴对象(即layout.xaxis)
   yaxis: {/* */}    // 与选定点关联的y轴对象
   zaxis: {/* */}    // 与选定点关联的z轴对象
  }, {
    /* 其他选定点类似 */
  }]
}

最后,请不要再使用plotly-latest.js或其缩小版本。虽然文档中还偶尔提到它们,但它们停留在版本1.58.5

请注意,从版本2开始,"plotly-latest"输出将不再在CDN上更新,并将保持在最后的v1补丁v1.58.5。因此,要在plotly.js v2及更高版本上使用CDN,你必须指定确切的plotly.js版本。

这是完整的代码:

<html>
  <head>
    <script src="https://cdn.plot.ly/plotly-2.18.1.min.js"></script>
    <style>
      .graph-container {
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .main-panel {
        width: 70%;
        float: left;
      }

      .side-panel {
        width: 30%;
        background-color: lightgray;
        min-height: 300px;
        overflow: auto;
        float: right;
      }
    </style>
  </head>
  <body>
    <div class="graph-container">
      <div id="myDiv" class="main-panel"></div>
      <div id="lineGraph" class="side-panel"></div>
    </div>
    <script>
      var nodes = [
        { x: 0, y: 0, z: 0, value: [1, 2, 3] },
        { x: 1, y: 1, z: 1, value: [4, 5, 6] },
        { x: 2, y: 0, z: 2, value: [7, 8, 9] },
        { x: 3, y: 1, z: 3, value: [10, 11, 12] },
        { x: 4, y: 0, z: 4, value: [13, 14, 15] }
      ];

      var edges = [
        { source: 0, target: 1 },
        { source: 1, target: 2 },
        { source: 2, target: 3 },
        { source: 3, target: 4 }
      ];

      var x = [];
      var y = [];
      var z = [];

      for (var i = 0; i < nodes.length; i++) {
        x.push(nodes[i].x);
        y.push(nodes[i].y);
        z.push(nodes[i].z);
      }

      var xS = [];
      var yS = [];
      var zS = [];
      var xT

<details>
<summary>英文:</summary>

Use `pointNumber` instead of `pointIndex`. You also need to fix the `type` of the second plot, for which I also suggest to set a fixed axis range (otherwise the axis will reset for each selected point) :

```lang-js
// max y value for the line plot
const ymax = Math.max(...nodes.map(n =&gt; n.value).flat());

document.getElementById(&#39;myDiv&#39;).on(&#39;plotly_click&#39;, function(data){
  var nodeIndex = data.points[0].pointNumber;
  var values = nodes[nodeIndex].value;

  Plotly.newPlot(&#39;lineGraph&#39;, [{
    type: &#39;scatter&#39;,
    mode: &#39;lines&#39;,
    x: [0, 1, 2],
    y: values
  }], {
    margin: { t: 0 },
    yaxis: {autorange: false, range: [0, ymax + 1]}
  });
});

For reference, here is the event data structure for 3d plots :

{
points: [{
curveNumber: 2,  // index in data of the trace associated with the selected point
pointNumber: 2,  // index of the selected point
x: 5,        // x value
y: 600,      // y value
z: 12,       // z value
data: {/* */},       // ref to the trace as sent to Plotly.newPlot associated with the selected point
fullData: {/* */},   // ref to the trace including all of the default attributes
xaxis: {/* */},   // ref to x-axis object (i.e layout.xaxis) associated with the selected point
yaxis: {/* */}    // ref to y-axis object &quot; &quot;
zaxis: {/* */}    // ref to z-axis object &quot; &quot;
}, {
/* similarly for other selected points */
}]
}

One last thing, don't use plotly-latest.js or its minified version anymore. While still referenced here and there in the documentation, they are stuck at version 1.58.5.

> Please note that as of v2 the "plotly-latest" outputs will no longer be updated on the CDN, and will stay at the last v1 patch v1.58.5. Therefore, to use the CDN with plotly.js v2 and higher, you must specify an exact plotly.js version.


Here is the complete code :

&lt;html&gt;
&lt;head&gt;
&lt;script src=&quot;https://cdn.plot.ly/plotly-2.18.1.min.js&quot;&gt;&lt;/script&gt;
&lt;style&gt;
.graph-container {
display: flex;
justify-content: center;
align-items: center;
}
.main-panel {
width: 70%;
float: left;
}
.side-panel {
width: 30%;
background-color: lightgray;
min-height: 300px;
overflow: auto;
float: right;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class=&quot;graph-container&quot;&gt;
&lt;div id=&quot;myDiv&quot; class=&quot;main-panel&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;lineGraph&quot; class=&quot;side-panel&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
var nodes = [
{ x: 0, y: 0, z: 0, value: [1, 2, 3] },
{ x: 1, y: 1, z: 1, value: [4, 5, 6] },
{ x: 2, y: 0, z: 2, value: [7, 8, 9] },
{ x: 3, y: 1, z: 3, value: [10, 11, 12] },
{ x: 4, y: 0, z: 4, value: [13, 14, 15] }
];
var edges = [
{ source: 0, target: 1 },
{ source: 1, target: 2 },
{ source: 2, target: 3 },
{ source: 3, target: 4 }
];
var x = [];
var y = [];
var z = [];
for (var i = 0; i &lt; nodes.length; i++) {
x.push(nodes[i].x);
y.push(nodes[i].y);
z.push(nodes[i].z);
}
var xS = [];
var yS = [];
var zS = [];
var xT = [];
var yT = [];
var zT = [];
for (var i = 0; i &lt; edges.length; i++) {
xS.push(nodes[edges[i].source].x);
yS.push(nodes[edges[i].source].y);
zS.push(nodes[edges[i].source].z);
xT.push(nodes[edges[i].target].x);
yT.push(nodes[edges[i].target].y);
zT.push(nodes[edges[i].target].z);
}
var traceNodes = {
x: x, y: y, z: z,
mode: &#39;markers&#39;,
marker: { size: 12, color: &#39;red&#39; },
type: &#39;scatter3d&#39;,
text: [0, 1, 2, 3, 4],
hoverinfo: &#39;text&#39;,
hoverlabel: {
bgcolor: &#39;white&#39;
},
customdata: nodes.map(function(node) {
if (node.value !== undefined)
return node.value;
}),
type: &#39;scatter3d&#39;
};
var layout = {
margin: { l: 0, r: 0, b: 0, t: 0 }
};
Plotly.newPlot(&#39;myDiv&#39;, [traceNodes], layout, { displayModeBar: false });
// max y value for the line plot
const ymax = Math.max(...nodes.map(n =&gt; n.value).flat());
document.getElementById(&#39;myDiv&#39;).on(&#39;plotly_click&#39;, function(data){
var nodeIndex = data.points[0].pointNumber;
var values = nodes[nodeIndex].value;
Plotly.newPlot(&#39;lineGraph&#39;, [{
type: &#39;scatter&#39;,
mode: &#39;lines&#39;,
x: [0, 1, 2],
y: values
}], {
margin: { t: 0 },
yaxis: {autorange: false, range: [0, ymax + 1]}
});
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

huangapple
  • 本文由 发表于 2023年2月8日 19:09:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75384907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定