How to change x-axis label in Stacked Area Chart NVD3.js? [duplicate] - html

I have a simple line graph with data in the format:
[
{
label: "lebel1",
x: 0,
y: 128
},
{
label: "lebel1",
x: 1,
y: 128
},
....
{
label: "lebel2",
x: 25,
y: 128
},
....
{
label: "lebel8",
x: 285,
y: 128
},
....
}
and I pass this into my nvd3 object:
nv.addGraph(function()
{
var chart = nv.models.lineChart();
chart.xAxis
.axisLabel("My X-Axis")
.ticks(36)
.tickFormat(function(d) { return d; });
chart.yAxis
.axisLabel('Voltage (v)')
.tickFormat(d3.format('.02f'));
d3.select('div svg')
.datum(myData)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(function() { d3.select(gridSvgId).call(chart) });
return chart;
});
How can I have my x-axis ticks to show:
* eight labels: label1 - label8
Rather than have the grids broken up into a variable number of lines?

Try something like this
chart.xAxis.tickValues(['Label 1','Label 2','Label 3','Label 4','Label 5','Label 6','Label 7','Label 8']);
or if you want to get it from the dataset, you could try something like this,
chart.xAxis.tickValues(function(d) {
// do all you stuff and return an array
var dataset = ['Build Array from data'];
return dataset;
};)
Hope it helps

Related

How to import and use a custom Chart.js plugin in Nuxt? (Chartjs-vuejs v2.9.4)

I am trying to import a custom plugin into my chart.
Got this plugin from my previous question: Question
Its a plugin so that I can use Grace in my version of Chart.js.
The version of Chart.js I am using is V2.9.4.
I am using vue-chartjs in Nuxt!.
Couldn't really find an answer anywhere else.
This is how it looks now
This is how I want it to look
Thanks in advance. :)
I made a Component called 'BarChart' in my Components folder.
I made a normal .vue file in my pages directory. In the <template> tag I added my <Barchart/> component.
In that same .vue file I added a script in the <script> tag.
The plugin code is included in the codes below, I didn't include it anywhere yet.
Barchart.vue (Component)
<script>
import {Bar} from "vue-chartjs";
export default {
extends: Bar,
props: {
data: {
type: String,
default: () => {},
},
options: {
type: Object,
default: () => {},
},
},
computed: {
Chart() {
return['data', 'options'];
},
},
mounted() {
this.renderChart(this.data, this.options);
},
};
</script>
.vue file (Include component)
<div class="chart">
<BarChart :data="barChartData" :options="barChartOptions" :height="200"/>
</div>
.vue file (script tags)
<script>
import BarChart from "~/components/plugins/BarChart";
export default {
components: {
BarChart,
},
data() {
return {
barChartData: {
labels: ["Verzonden", "Ontvangen", "Geopend", "Kliks"],
datasets: [
{
data: [25, 20, 20, 18],
backgroundColor: [
'#7782FF',
'#403DD3',
'#FFB930',
'#00E437',
],
barThickness : 50,
},
],
},
barChartOptions: {
responsive: true,
legend: {
display: false,
},
scales: {
xAxes: [
{
gridLines: {
display: false,
},
ticks: {
fontColor: "black",
fontSize: 14,
},
},
],
yAxes: [
{
ticks: {
beginAtZero: true,
min: 0,
stepSize: 5,
fontColor: '#ABACB3',
},
gridLines: {
display: true,
borderDash: [4, 4],
color: '#EEEDFB',
drawBorder: false,
},
},
],
},
},
};
},
};
</script>
Plugin code (where do I put this and how do I make it work?)
const plugin = {
id: "customScale",
beforeLayout: (chart, options, c) => {
let max = Number.MIN_VALUE;
let min = Number.MAX_VALUE
let grace = options.grace || 0
chart.data.datasets.forEach((dataset) => {
max = Math.max(max, Math.max(...dataset.data));
min = Math.min(min, Math.min(...dataset.data))
})
if (typeof grace === 'string' && grace.includes('%')) {
grace = Number(grace.replace('%', '')) / 100
chart.options.scales.yAxes[0].ticks.suggestedMax = max + (max * grace)
chart.options.scales.yAxes[0].ticks.suggestedMin = min - (min * grace)
} else if (typeof grace === 'number') {
chart.options.scales.yAxes[0].ticks.suggestedMax = max + grace
chart.options.scales.yAxes[0].ticks.suggestedMin = min - grace
}
}
}
According to the vue-chartjs documentation you can do this in 2 ways.
If you want the plugin to be available for all your charts you can use the global registration like so:
import Chart from 'chart.js'
Chart.pluginService.register({
id: "customScale",
beforeLayout: (chart, options, c) => {
let max = Number.MIN_VALUE;
let min = Number.MAX_VALUE
let grace = options.grace || 0
chart.data.datasets.forEach((dataset) => {
max = Math.max(max, Math.max(...dataset.data));
min = Math.min(min, Math.min(...dataset.data))
})
if (typeof grace === 'string' && grace.includes('%')) {
grace = Number(grace.replace('%', '')) / 100
chart.options.scales.yAxes[0].ticks.suggestedMax = max + (max * grace)
chart.options.scales.yAxes[0].ticks.suggestedMin = min - (min * grace)
} else if (typeof grace === 'number') {
chart.options.scales.yAxes[0].ticks.suggestedMax = max + grace
chart.options.scales.yAxes[0].ticks.suggestedMin = min - grace
}
}
});
This way of importing and registering should work from anywhere in your app.
The second way is an inline plugin. This needs to be done in your BarChart.vue and goes like this:
mounted() {
this.addPlugin(
Chart.pluginService.register({
id: "customScale",
beforeLayout: (chart, options, c) => {
let max = Number.MIN_VALUE;
let min = Number.MAX_VALUE
let grace = options.grace || 0
chart.data.datasets.forEach((dataset) => {
max = Math.max(max, Math.max(...dataset.data));
min = Math.min(min, Math.min(...dataset.data))
})
if (typeof grace === 'string' && grace.includes('%')) {
grace = Number(grace.replace('%', '')) / 100
chart.options.scales.yAxes[0].ticks.suggestedMax = max + (max * grace)
chart.options.scales.yAxes[0].ticks.suggestedMin = min - (min * grace)
} else if (typeof grace === 'number') {
chart.options.scales.yAxes[0].ticks.suggestedMax = max + grace
chart.options.scales.yAxes[0].ticks.suggestedMin = min - grace
}
}
});
)
}

ngx-slider - config step is 50 and can dynamic value

I'm using ngx-slider in angular9, and config like this:
options = {
floor: 0,
ceil: 1000,
step: 50,
hideLimitLabels: true,
translate: (value: number): string => {
return '$' + value;
}
}
value = 46;
<ngx-slider [(value)]="value" [options]="options" (userChangeEnd)="onUserChangeEnd()"></ngx-slider>
And the slider will show at $50 point the first time.
I want it will show at the $46 point base on the value.
How can I do that?
Did you try floor value as 46
options = {
floor: 46,
ceil: 1000,
step: 50,
hideLimitLabels: true,
translate: (value: number): string => {
return '$' + value;
}
}

How do I use JavaScript regexes to return objects with in a array?

I am trying to use regexes to convert my JSON file that is returned into separate objects using [] not () so I can then push an id out of each of these objects. I am able to get the intial JSON object to return I need to turn those objects into arrays.
reference: Google APp script Get Properties
JS
var GetShapeProps = [{
({
id: "6:3",
absoluteBoundingBox: [{
x: -406,
y: -274,
width: 437,
height: 56
})
}),
({
id: "10:3",
absoluteBoundingBox: [{
x: -406,
y: -201,
width: 437,
height: 56
})
}),
({
id: "10:4",
absoluteBoundingBox: [{
x: -406,
y: -122,
width: 437,
height: 56
})
}),
({
id: "10:5",
absoluteBoundingBox: [{
x: -406,
y: -28,
width: 437,
height: 56
})
}]
function prop1(obj1, getFrameProps, b, args){
function prop2(obj1, getFrameProps, keys, b, kind) {
var GetShapesProps = GetFrammeProps;
obj1 = PropertiesService.GetShapesProps();
// Sets several script properties, then retrieves them and logs them.
GetShapesProaps = GetShapesProaps.getProperties();
for (var id in GetShapesProaps) {
if (id > GetShapesProaps) {
var newObject = (kind, GetShapesProaps[id]);
}
}
}
}
output Srings:
[id: "6:3"]
[{ x: -406,
y: -274,
width: 437,
height: 56}]
Error Returned
TypeError: Cannot find function replace in object
[object Object],[object Object],
[object Object],[object Object],
[object Object],[object Object].

Loss and mean squared error values not showing during training performance. Not getting predicted line

Currently we are trying to input uber data that includes time of day and ride fare into our TensorFlow.js model. We noticed that when we ran the model on the browser, the points are showing up on our scatterplot but during the training the loss and mean squared error values are not showing up and most importantly our model is not displaying a prediction line.
var userData = [
{
"City": "San Francisco",
"Product_Type": "UberEATS Marketplace",
"Trip_or_Order_Status": "COMPLETED",
"Request_Time": "2019-06-16 04:10:44 +0000 UTC",
"Begin_Trip_Time": "2019-06-16 04:44:40 +0000 UTC",
"Begin_Trip_Lat": "37.7352602",
"Begin_Trip_Lng": "-122.4203465",
"Begin_Trip_Address": "",
"Dropoff_Time": "2019-06-16 04:44:40 +0000 UTC",
"Dropoff_Lat": "37.7352602",
"Dropoff_Lng": "-122.4203465",
"Dropoff_Address": "",
"Distance_miles": "2.04",
"Fare_Amount": "32.34",
"Fare_Currency": "USD"
}...]
async function getData() {
const carsData = await userData;
// Here we map out the values for each car and filter out the list item that do not have an day or a pay value
const cleaned = carsData.map(car => ({
timeInMinutes: calculateMins(car.Request_Time),
pay_rate: normalizeUberPrice(car.Distance_miles, car.Fare_Amount),
}))
.filter(car => (car.day != null && car.pay != null));
return cleaned;
}
async function run() {
const data = await getData();
const values = data.map(d => ({
x: d.day,
y: d.pay,
}));
tfvis.render.scatterplot(
{ name: 'Horsepower v MPG' },
{ values },
{
xAxisDomain: [0, 1600],
yAxisDomain: [0,10],
xLabel: 'Day',
yLabel: 'Pay',
height: 300
}
);
const model = createModel();
tfvis.show.modelSummary({ name: 'Model Summary' }, model);
// Convert the data to a form we can use for training.
const tensorData = convertToTensor(data);
console.log(tensorData)
const { inputs, labels } = tensorData;
// Train the model
await trainModel(model, inputs, labels);
console.log('Done Training');
testModel(model, data, tensorData);
}
function createModel() {
const model = tf.sequential();
model.add(tf.layers.dense({ inputShape: [1], units: 25, useBias: true }));
model.add(tf.layers.dense({ units: 50, activation: "sigmoid" }));
model.add(tf.layers.dense({ units: 1, useBias: true }));
return model;
}
function convertToTensor(data) {
return tf.tidy(() => {
tf.util.shuffle(data);
const inputs = data.map(d => d.pay)
const labels = data.map(d => d.day);
const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);
const labelTensor = tf.tensor2d(labels, [labels.length, 1]);
//Step 3. Normalize the data to the range 0 - 1 using min-max scaling
const inputMax = inputTensor.max();
const inputMin = inputTensor.min();
const labelMax = labelTensor.max();
const labelMin = labelTensor.min();
const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));
return {
inputs: normalizedInputs,
labels: normalizedLabels,
// Return the min/max bounds so we can use them later.
inputMax,
inputMin,
labelMax,
labelMin,
}
});
}
async function trainModel(model, inputs, labels) {
model.compile({
optimizer: tf.train.adam(),
loss: tf.losses.meanSquaredError,
metrics: ['mse'],
});
const batchSize = 32;
const epochs = 30;
callbacks: tfvis.show.fitCallbacks(
{ name: 'Training Performance' },
['loss', 'mse'],
{
xAxisDomain: [0, 100],
yAxisDomain: [0,1],
height: 200,
callbacks: ['onEpochEnd'] }
// ',onBatchEnd'
),
history: tfvis.show.history({
name: 'History'},
history,
["loss","mse"])
});
}
function testModel(model, inputData, normalizationData) {
const { inputMax, inputMin, labelMin, labelMax } = normalizationData;
const [xs, preds] = tf.tidy(() => {
const xs = tf.linspace(0, 1, 100);
const preds = model.predict(xs.reshape([100, 1]));
const unNormXs = xs
.mul(inputMax.sub(inputMin))
.add(inputMin);
const unNormPreds = preds
.mul(labelMax.sub(labelMin))
.add(labelMin);
return [unNormXs.dataSync(), unNormPreds.dataSync()];
});
const predictedPoints = Array.from(xs).map((val, i) => {
return { x: val, y: preds[i] }
});
const originalPoints = inputData.map(d => ({
x: d.pay, y: d.day,
}));
console.log("ORIGINAL POINTS:")
console.log(originalPoints)
tfvis.render.scatterplot(
{ name: 'Model Predictions vs Original Data' },
{ values: [originalPoints, predictedPoints], series: ['original', 'predicted'] },
{
xAxisDomain: [0,10],
yAxisDomain: [0,1600],
xLabel: 'Horsepower',
yLabel: 'MPG',
height: 1000
}
);
}
document.addEventListener('DOMContentLoaded', run);
Basically we want to see a predicted line for our data but were not getting anything back.
It worked when we used data like this:
var userData = [{
day: 1
pay: 20
},...]
The data processing is not well performed. Thus, the values used for prediction contain NaN and Infinity. As a result, the error computed by model.fit is NaN and could therefore not be displayed on the chart of tfjs-vis.
The filtering
.filter(car => (car.day != null && car.pay != null));
is not removing NaN and Infinity. Instead, this condition can be used:
.filter(car => isFinite(car.pay + car.day) && !isNaN(car.pay + car.day));
Though, the NaN and Infinity are found within the values of car.day, here a general filtering is made over car.pay and car.day - thus the additional operation - to make sure that these values will not appear anywhere in the cleaned data.
here you can see how to display the loss.

Highcharts and JSON

Let me know how to declare multiple data in Y because my script doesn't work.
My JSON file is:
[{"metier":"Administratif","annee2005":182373,"annee2006":188153,"annee2007":194636},
{"metier":"Igenieur","annee2005":9140,"annee2006":9483,"annee2007":4321},
{"metier":"Chef de chantier","annee2005":25118,"annee2006":29417,"annee2007":32081},
{"metier":"Commercial","annee2005":13122,"annee2006":16294,"annee2007":17706}]
My Javascript is
$.getJSON('dataTest.json', function(data) {
var output = [];
$.each(data,function(i,d){
output.push(
{
name: d.metier,
y: [d.annee2005,d.annee2006]
}
);
});
$('#container').highcharts({
chart:{
type:'column'
},
xAxis:{
type:'category'
},
series: [{
name: 'Métiers',
data: output
}
]
});
});
In output.y you have array of two values but it must be one value for y, you need create 2 series for output 2 graphics