Plotly.js multiple subplots not working as expected - javascript

Edit to add: Looking for the "plotly.js" way to do this. This "small multiple" visualization should have some "plotly.js" solution out there but haven't found it yet.
I am using an array (example element below) to populate traces for plotly.js multiple subplots per their multiple-subplots example
[{
"key": "Ontario|Toronto",
"values": [{
"key": "2020-01-25",
"value": 1
}, {
"key": "2020-01-27",
"value": 1
}, {
"key": "2020-05-12",
"value": 218
}, {
"key": "2020-05-13",
"value": 169
}]
}, {
etc
}]
The array has 94 elements which contain info needed to create each trace. This would result in 94 subplots, one per trace. This plotly.js visualization could also be called "small multiples".
I am creating the traces dynamically and populating subplot definitions in a loop using code below:
// create chart data
var traces = [];
var rowCount = (caseRegionByDate.length / 2).toFixed()
for (var i=0; i<caseRegionByDate.length; i++) {
//console.log(caseRegionByDate[i]['key']);
var trace = {};
var x = [];
var y = [];
for (var j=0; j<caseRegionByDate[i]['values'].length; j++) {
//console.log(caseRegionByDate[i]['values'][j]['key']);
x.push(caseRegionByDate[i]['values'][j]['key']);
y.push(caseRegionByDate[i]['values'][j]['value']);
}
// create trace i
trace = {
"x":x,
"y":y,
"xaxis":"x"+i,
"yaxis":"y"+i,
"type":"scatter"
}
// push trace to traces
traces.push(trace);
}
console.log(JSON.stringify(traces));
var layout = {
grid: {rows: rowCount, columns: 2, pattern: 'independent'},
};
Plotly.newPlot('multiple_charts', traces, layout);
This creates the traces variable populated by each trace that looks like example below. It looks correct:
[{
"x": ["2020-03-16", "2020-03-23", "2020-03-24", "2020-03-25", "2020-03-31", "2020-04-01", "2020-04-02", "2020-04-03", "2020-04-06", "2020-04-07", "2020-04-08", "2020-04-09", "2020-04-10", "2020-04-11", "2020-04-13", "2020-04-14", "2020-04-15", "2020-04-16", "2020-04-17", "2020-04-18", "2020-04-21", "2020-04-22", "2020-04-23", "2020-04-24", "2020-04-25", "2020-04-26", "2020-04-27", "2020-04-28", "2020-04-29", "2020-04-30", "2020-05-01", "2020-05-02", "2020-05-03", "2020-05-04", "2020-05-05", "2020-05-06", "2020-05-07", "2020-05-08", "2020-05-09", "2020-05-10", "2020-05-11", "2020-05-12", "2020-05-13"],
"y": [1, 1, 1, 1, 9, 35, 3, 16, 33, 13, 9, 5, 5, 1, 22, 3, 4, 7, 19, 4, 7, 2, 18, 11, 9, 9, 9, 13, 1, 3, 7, 18, 5, 4, 4, 5, 3, 1, 2, 2, 3, 1, 2],
"xaxis": "x0",
"yaxis": "y0",
"type": "scatter"
}, {
"x": ["2020-03-14", "2020-03-26", "2020-03-27", "2020-04-02", "2020-04-06", "2020-04-09", "2020-04-14", "2020-04-17", "2020-04-18", "2020-04-20", "2020-04-22"],
"y": [1, 1, 1, 2, 2, 3, 1, 1, 1, 2, 1],
"xaxis": "x1",
"yaxis": "y1",
"type": "scatter"
},
etc
]
However, the result appears to be one row with two columns that have all of the traces (there are 94 traces) squashed into them. Here is screenshot.
Any ideas what is happening? I expect to have 48 rows with 2 columns, one subplot per trace.
The only difference from the multiple subplots example is that my xaxis have date strings instead of numbers. Everything else is same.

The subplots are actually being created in 3 x rowCount grid. However they are all squashed vertically as in screenshot.
It appears that a chart's default height and width dimensions, where they are not explicitly defined using layout.height, are what is shown in my screenshot eg too small for 94 subplots.
The quick fix is to simply increase the chart's layout.height size. Then all subplots are visible. Dynamically calculating layout.height, in spirit of Juan's suggestion, relative to number of rows works well.
Apparently it is also possible to set each subplot's x and y domain attributes to resize subplots which will also give desired results.

Related

Why is this color incorrect in Sankey R plot?

The code below generates a Sankey diagram. However, as you can see in Figure 1, the "No Change" box is orange ("#eb6841"), not yellow ("Yellow"). This does not appear to correspond to the code, where I specified yellow as the colour I wanted. Does anyone know why it is orange and not yellow? It also looks like the box colour on the left is not always the same as the line colour, which is also wrong. Any help appreciated. Thanks.
Code:
library(networkD3)
## create a dataframe with 12 nodes
nodes = data.frame("name" = c("Demographics",
"Inequality",
"Productivity",
"Urbanisation",
"Balance of Payments",
"Consumption",
"Debt",
"FDI",
"Trade Deals",
"Currency",
"Positive",
"No Change",
"Negative"))
## create edges with weights
links = as.data.frame(matrix(c(0, 12, 2,
1, 11, 2,
2, 10, 2,
3, 10, 2,
4, 11, 2,
5, 10, 2,
6, 12, 2,
7, 11, 2,
8, 10, 2,
9, 11, 2
), byrow = TRUE, ncol = 3))
## set column names for links
names(links) = c("source", "target", "value")
## add edge types for coloring purpose
links$group <- c("group_1",
"group_1",
"group_2",
"group_2",
"group_3",
"group_3",
"group_4",
"group_4",
"group_5",
"group_5")
## Create custom color list using d3 for each node
node_color <- 'd3.scaleOrdinal() .domain(["Demographics",
"Inequality",
"Productivity",
"Urbanisation",
"Balance of Payments",
"Consumption",
"Debt",
"FDI",
"Trade Deals",
"Currency",
"Positive",
"No Change",
"Negative",
"group_1",
"group_2",
"group_3",
"group_4",
"group_5"]) .range(["#edc951", "#edc951", "#eb6841", "#eb6841", "#cc2a36", "#cc2a36", "#4f372d", "#4f372d", "#00a0b0", "#00a0b0", "Green", "Yellow", "Red", "#edc951", "#eb6841", "#cc2a36", "#4f372d", "#00a0b0"])'
## Draw Sankey Diagram
p = sankeyNetwork(Links = links, Nodes = nodes,
Source = "source", Target = "target",
Value = "value", NodeID = "name",
fontSize = 14, nodeWidth = 40,
colourScale = node_color,
LinkGroup = "group")
p
Figure 1:
The group names can not have spaces in them. It will only consider the text before the first space.

How to pass a variable from c# into javascript for plotting in plotly.js

I am trying to pass X and Y data generated in c# into plotly.js that update every second (or as often as programmatically possible). How would I reference in javascript a variable like x and y located in the .json file or c#? Ultimately, the javascript piece should run plotly with x and y taken from the c# code (Or in c#, I can generate a .json file every second). Plotly allows for dynamic updating, so this should be possible if the variables can be passed. I have included my starting point below:
C# Code:
dataPoint.X = 0;
dataPoint.Y = retrieveVariable(MachineInfoService.Instance.machineInfo.plot, 0);
xstr = dataPoint.X.ToString();
ystr = dataPoint.Y.ToString();
for (i = 1; i < numdataPoints; i++)
{
dataPoint.X = i;
dataPoint.Y = retrieveVariable(MachineInfoService.Instance.machineInfo.plot, i);
xstr =xstr +", " +dataPoint.X.ToString();
ystr = ystr +", "+ dataPoint.Y.ToString();
Globals.PlotlyX = xstr;
Globals.PlotlyY = ystr;
graphData.Add(dataPoint);
}
webView.Navigate(new Uri("ms-appx-web:///Assets/index3.html"));
index3.html:
<html>
<head>
<!-- Plotly.js -->
<!----<script src="https://cdn.plot.ly/plotly-latest.min.js"></script> -->
<script src="plotly-latest.min.js"></script>
<script type="text/javascript" src="../Assets/xydata.json"></script>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<!-- Plotly chart will be drawn inside this DIV -->
<div id="graphDiv"></div>
<script>
jQuery.get('../Assets/xydata.json');
Plotly.newPlot('plotly-chart', data, layout);
</script>
</body>
</html>
xydata.json:
{
"data": [
{
"x": [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ],
"y": [ 0, 3, 6, 4, 5, 2, 3, 5, 4 ],
"type": "scatter",
"name": "Plot 1"
},
{
"x": [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ],
"y": [ 0, 4, 7, 8, 3, 6, 3, 3, 4 ],
"type": "scatter",
"name": "Plot 2"
},
{
"x": [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ],
"y": [ 0, 5, 3, 10, 5.33, 2.24, 4.4, 5.1, 7.2 ],
"type": "scatter",
"name": "Plot 3"
}
],
"layout": {
"showlegend": true,
"legend": { "orientation": "h" }
}
}
I wouldn't write to a file for each plot update. The cleanest way would probably be to use Newtonsoft's Json.NET which helps you convert .NET objects to JSON. If you don't want to use another library, you could also just manually format a String into valid JSON, but that may be much more complicated/error prone.
After having new plot data, call the function via C#, like this:
PlotyObject data = new PlotyObject()
webView.Document.InvokeScript("updatePlotWithNewData", {JsonConvert.SerializeObject(data)})
OR
webView.Document.InvokeScript("updatePlotWithNewData", {"{...manually formatted JSON...}"})
In your index3.html file, you could do something like this to accept new data and update the Ploty chart:
<script>
var plotlyData = {...}
var layout = { ... }
$(document).ready(function() {
Plotly.newPlot('plotly-chart', plotlyData, layout);
});
function updatePlotWithNewData(newData) {
plotlyData = JSON.parse(newData);
Plotly.redraw('plotly-chart');
}
</script>

Load data from json in tabulator?

I have this json variable and want to draw table by tabulator:
mydata=
[
{
"trade_symbol": "Media",
"technical_sum_List": [
19,
5,
4
],
"volume_sum_List": [
6,
1
],
"pivot_sum_list": [
5,
0,
0
]
},
{
"trade_symbol": "Sport",
"technical_sum_List": [
18,
4,
4
],
"volume_sum_List": [
3,
4
],
"pivot_sum_list": [
5,
0,
0
]
},
{
"trade_symbol": "Dance",
"technical_sum_List": [
13,
10,
5
],
"volume_sum_List": [
1,
6
],
"pivot_sum_list": [
2,
2,
0
]
}
]
Now I want to insert technical_sum_List[1] or technical_sum_List[2] in each columns by tabulator.
in tabulator we can only use field:"technical_sum_List" and do not accept technical_sum_List[1]!
There might be an easier way but you can do this through using a customFormatter. The gist is that when you define your table columns, you add a formatterParam which tells Tabulator which index in the array to reference and the name of the custom formatter function. Defining a separate function means you can reuse it for all your arrays.
{title:"B-1", field:"technical_sum_List", formatterParams: {index:0}, formatter: customFormatter},
Get the cell value and then use the formatterParams to reference and return the data at that array position.
function customFormatter(cell, formatterParams) {
return cell.getValue()[formatterParams.index];
}
let myData = [{
"trade_symbol": "Media",
"technical_sum_List": [
19,
5,
4
],
"volume_sum_List": [
6,
1
],
"pivot_sum_list": [
5,
0,
0
]
},
{
"trade_symbol": "Sport",
"technical_sum_List": [
18,
4,
4
],
"volume_sum_List": [
3,
4
],
"pivot_sum_list": [
5,
0,
0
]
},
{
"trade_symbol": "Dance",
"technical_sum_List": [
13,
10,
5
],
"volume_sum_List": [
1,
6
],
"pivot_sum_list": [
2,
2,
0
]
}
]
var table = new Tabulator("#example-table", {
height:"311px",
columns:[
{title:"A", field:"trade_symbol"},
{title:"B-1", field:"technical_sum_List",
formatterParams: {index:0},
formatter: customFormatter},
{title:"B-2", field:"technical_sum_List",
formatterParams: {index:1},
formatter: customFormatter},
{title:"B-3", field:"technical_sum_List",
formatterParams: {index:2},
formatter: customFormatter},
],
});
function customFormatter(cell, formatterParams) {
return cell.getValue()[formatterParams.index];
}
table.setData(myData);
<link href="https://unpkg.com/tabulator-tables#4.5.3/dist/css/tabulator.min.css" rel="stylesheet"/>
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.5.3/dist/js/tabulator.min.js"></script>
<div id="example-table"></div>
#spring is right, you can only traverse object not arrays for column bindings.
#spring's approach may work, but you would have to be careful as filters and sorting would only see the array not the data.
A better approach would probably to use mutators, which would then make the data accessible to filters and sorters. so we can take #springs code and with a couple of tweaks make it work:
//define mutator
function customMutator(value, data, type, params) {
return data[params.field][params.index];
}
//assign mutator to columns
var table = new Tabulator("#example-table", {
height:"311px",
columns:[
{title:"A", field:"trade_symbol"},
{title:"B-1", field:"b1",
mutatorParams: {index:0, field:"technical_sum_List"},
mutator: customMutator},
{title:"B-2", field:"b2",
mutatorParams: {index:1, field:"technical_sum_List"},
mutator: customMutator},
{title:"B-3", field:"b3",
mutatorParams: {index:2, field:"technical_sum_List"},
mutator: customMutator},
],
});
This approach has several benefits, it means columns can be sorted and filtered and included in downloads.
It also means that now each column has its own unique field, so can be more easily looked-up from outside the table.
in summary formatters are visual only and DO NOT affect sorting and filtering. mutators on the other hand update the underlying data and DO affect sorting, filtering and everything else.
More details of this can be found in the Mutator Documentation
Thank you.
I found best answer:
We must use formatter: customFormatter
function customFormatter(cell, params) {
return cell.getValue()[params.myid].rvalue;
}
for(var r=0;r<alldata[0].result.length;r++){
table.addColumn({title:alldata[0].result[r].alias_title ,field:"result", formatterParams: {myid:r}, formatter: customFormatter});
}

Nested synchronous loops in NodeJS

So I have an array of object that I want to use for my server, each object has the same amount of keys.
Here is a simplified version of the array:
[{
"BTQ": 1,
"COLLIC": "Foo1",
"MMC": "Bar1",
"PTURE": 39,
"STOCK": 6,
},
{
"BTQ": 1,
"COLLIC": "Foo1",
"MMC": "Bar2"",
"PTURE": 31,
"STOCK": 2,
},
{
"BTQ": 2,
"COLLIC": "Something1",
"MMC": "AnotherThing1",
"PTURE": 40,
"STOCK": 5,
},
{
"BTQ": 2,
"COLLIC": "Something1",
"MMC": "AnotherThing1",
"PTURE": 11,
"STOCK": 7,
}]
and I want to build a function that loops through all of these objects, and builds another JSON array that looks like that:
[
{
"BTQ": 1,
"COLLICs": {
"Foo1": {
"Bar1": {
"Stock": 6,
"PTURE" {"39": 6}
},
"Bar2": {
"Stock": 2,
"PTURE": {"31": 2,}
}
}
}
},
{
"BTQ": 2,
"COLLICs": {
"Something1": {
"AnotherThing1": {
"Stock": 12,
"PTURE": {"40": 5, "11": 7}
}
}
}
},
//etc ...
]
I am using NodeJS, and I figured out I needed to build a function like this one :
function step(i){
if (i < raw.length){
data.push(raw[i].A);
step(i + 1);
} else {
console.log("Finished");
console.log(data);
}
}
but the thing is I don't know how to nest this function...
Here is what I want to achieve in the end:
1) Loop through each object in the raw array (done with the function above)
2) For each object, loop through data (the sorted array) and see if any of the objects in there has the same "BTQ" value, if so : go into the object, and see if the raw[i].COLLIC exists the data[j].COOLLICs' keys. If exists, look if the MMC exists, ETC ... If any of the values does not exist, create a new key/object which stores all the informations, and then start again with the following raw object.
It is probably not very clear and I'm sorry for that, if it can help, I had built the same algorithm but with for loops, I can paste it here if it could help to make things clearer.
I really hope you can help me because I'm loosing my mind on this ...
Thanks ! Ali

How to push data to same array in java script in several time in same function?

I'm getting values from database in json structure. and i want to display them in table in javascript.Data come in following format.
"free_issue": [
{
"product_id": [14, 15, 16],
"free_product_ids": [15],
"structure": [
{
"req_qty": 10,
"free_qty": 2
},
{
"req_qty": 20,
"free_qty": 5
},
{
"req_qty": 50,
"free_qty": 10
}
]
}
From those data i want to push this data to table row. data in same row with 4 columns.I used array push method to push data. but i'm unable to get it in correct way.
in here all the data should in one row.
Please help me to do this.......
have You tried to do like this?
"free_issue": [
{
"product_id": [14, 15, 16],
"free_product_ids": [null, 15, null],
"structure": [
{
"req_qty": 10,
"free_qty": 2
},
{
"req_qty": 20,
"free_qty": 5
},
{
"req_qty": 50,
"free_qty": 10
}
]
}
I mean You've to generate these arrays before and then attach these arrays to fields of object. Notice: all of arrays must be same length to be able aligned to correct rows.

Categories

Resources