Categories
Pengumuman

Trendline pada Chart

//AI assist this code
//Sample
// Your provided JSON data
// const jsonData = [{
//   "name": "TRM 2025",
//   "data": [264, 322, 272, 475, 305, 792, 542, 650, 0, 0, 0, 114],
//   "type": "column"
// }, {
//   "name": "TRM 2024",
//   "data": [174, 257, 172, 338, 347, 681, 591, 641, 208, 1, 0, 49],
//   "type": "line"
// }, {
//   "name": "TRM 2023",
//   "data": [359, 126, 285, 306, 401, 544, 623, 583, 423, 69, 0, 3],
//   "type": "line"
// }];

//imagine you have three data row in a data series
//then you want to make a trendline for a specific data row
function calculateTrendline(data, seriesName, isCombinedResult=true, stopOnZero=false) {
  // Find the specific series data you need
  const series = data.find(s => s.name === seriesName);

  if (!series) {
    console.error(`Series with name "${seriesName}" not found.`);
    return [];
  }

  const yValues = series.data;
  const n = yValues.length;
  // x-values are just the index of each data point, starting from 1
  const xValues = Array.from({
    length: n
  }, (_, i) => i+1);

  // Calculate the necessary sums
  let sumX = 0;
  let sumY = 0;
  let sumXY = 0;
  let sumX2 = 0;
  let istop = -1;

  for (let i = 0; i < n; i++) {
    if (stopOnZero && yValues[i] == 0) {
        istop = i;
        break;
    }
    sumX += xValues[i];
    sumY += yValues[i];
    sumXY += xValues[i] * yValues[i];
    sumX2 += xValues[i] * xValues[i];
  }

  ntrend = stopOnZero ? istop : n;
  
  //Calculate the slope (m) and y-intercept (b)
  const m = (ntrend * sumXY - sumX * sumY) / (ntrend * sumX2 - sumX * sumX);
  const b = (sumY / ntrend) - (m * (sumX / ntrend));
  //console.log('m = ('+ntrend+' * '+sumXY+' - '+sumX+' * '+sumY+') / ('+ntrend+' * '+sumX2+' - '+sumX+' * '+sumX+')')
  //console.log('b = ('+sumY+' / '+ntrend+') - ('+m+' * ('+sumX2+' / '+sumX+'))')

  // Generate the new data points for the trendline
  const trendlineData = [];
  for (let i = 0; i < n; i++) {
    if (stopOnZero && i == istop) {
        break;
    }
    // The y-value of the trendline is calculated using y = mx + b
    const yTrend = m * xValues[i] + b;
    trendlineData.push(yTrend);
  }
  
  // Array to hold new trendlines
  const chartSeries = [];
  if (isCombinedResult) {
      data.forEach(series => {
        // Add the original series to the chart series array
        chartSeries.push(series);
      });
  }
  // Add the new trendline series to the chart series array
  chartSeries.push({
    name: `${seriesName} Trendline`,
    data: trendlineData,
    type: 'line', // Trendlines are best represented as lines
  });
  
  return chartSeries;
}

// --- Example Usage ---
// To get the trendline data for "TRM 2024"
//const trendlineData = calculateTrendline(jsonData, "TRM 2024", true, true);
//console.log(trendlineData);

//imagine you have three data row in a data series
//then you want to make a trendline for each data row, then will be three trendline (since you have three data row)
function calculateAllTrendline(data, isCombinedResult=true, stopOnZero=false) {
  // Array to hold all original series and their new trendlines
  const chartSeries = [];

  // Iterate through each series in your JSON data
  jsonData.forEach(series => {
    if (isCombinedResult) {
        // Add the original series to the chart series array
        chartSeries.push(series);
    }

    // Calculate the trendline for the current series' data
    const trendlineData = calculateRowTrendline(series.data, stopOnZero);

    // Add the new trendline series to the chart series array
    chartSeries.push({
    name: `${series.name} Trendline`,
    data: trendlineData,
    type: 'line', // Trendlines are best represented as lines
    });
  });
  return chartSeries;
}

function calculateRowTrendline(data, stopOnZero=false) {
  const n = data.length;
  // The x-values are the index of each data point, starting from 1
  const xValues = Array.from({ length: n }, (_, i) => i+1);

  // Calculate the necessary sums
  let sumX = 0;
  let sumY = 0;
  let sumXY = 0;
  let sumX2 = 0;
  let istop = -1;

  for (let i = 0; i < n; i++) {
    if (stopOnZero && data[i] == 0) {
        istop = i;
        break;
    }
    sumX += xValues[i];
    sumY += data[i];
    sumXY += xValues[i] * data[i];
    sumX2 += xValues[i] * xValues[i];
  }

  ntrend = stopOnZero ? istop : n;
  
  //Calculate the slope (m) and y-intercept (b)
  const m = (ntrend * sumXY - sumX * sumY) / (ntrend * sumX2 - sumX * sumX);
  const b = (sumY / ntrend) - (m * (sumX / ntrend));
  //console.log('m = ('+ntrend+' * '+sumXY+' - '+sumX+' * '+sumY+') / ('+ntrend+' * '+sumX2+' - '+sumX+' * '+sumX+')')
  //console.log('b = ('+sumY+' / '+ntrend+') - ('+m+' * ('+sumX2+' / '+sumX+'))')

  // Generate the new data points for the trendline
  const trendlineData = [];
  for (let i = 0; i < n; i++) {
    if (stopOnZero && i == istop) {
        break;
    }
    const yTrend = m * xValues[i] + b;
    trendlineData.push(yTrend);
  }

  return trendlineData;
}

// --- Example Usage ---
//const trendlineAllData = calculateAllTrendline(jsonData, false, true);
//console.log(trendlineAllData);

//imagine you have three data row in a data series
//then you want to make a trendline for all your rows (combined)
function calculateCombinedTrendline(jsonData, isCombinedResult=true, stopOnZero=false) {
  // 1. Combine all the data from all series into a single array
  const combinedYValues = [];
  jsonData.forEach(series => {
    combinedYValues.push(...series.data);
  });
  
  const nseries = jsonData.length;
  const n = combinedYValues.length;
  const serieslength = n/nseries;
  // 2. The x-values are a continuous sequence from 1 to n
  const combinedXValues = Array.from({ length: serieslength }, (_, i) => i+1);

  // 3. Calculate the sums for linear regression
  let sumX = 0;
  let sumY = 0;
  let sumXY = 0;
  let sumX2 = 0;
  let istop = serieslength + 1;
  
  //find istop
  for (let s = 0; s < nseries; s++) {
    for (let i = 0; i < serieslength; i++) {
      if (stopOnZero && combinedYValues[(serieslength*s)+i] == 0) {
        if (i < istop) {
          istop = i;
        }
        break;
      }
    }
  }

  for (let s = 0; s < nseries; s++) {
    for (let i = 0; i < serieslength; i++) {
      let si = (serieslength*s)+i;
      if (stopOnZero && i == istop) {
        break;
      }
      sumX += combinedXValues[i];
      sumY += combinedYValues[si];
      sumXY += combinedXValues[i] * combinedYValues[si];
      sumX2 += combinedXValues[i] * combinedXValues[i];
    }
  }

  ntrend = stopOnZero ? istop*nseries : n;
  
  // 4. Calculate the slope (m) and y-intercept (b)
  const m = (ntrend * sumXY - sumX * sumY) / (ntrend * sumX2 - sumX * sumX);
  const b = (sumY / ntrend) - (m * (sumX / ntrend));
  //console.log('m = ('+ntrend+' * '+sumXY+' - '+sumX+' * '+sumY+') / ('+ntrend+' * '+sumX2+' - '+sumX+' * '+sumX+')')
  //console.log('b = ('+sumY+' / '+ntrend+') - ('+m+' * ('+sumX2+' / '+sumX+'))')

  // 5. Generate the new data points for the single trendline
  const trendlineData = [];
  //get the first row on the series
  for (let i = 0; i < serieslength; i++) {
    let si = i;
    if (stopOnZero && si == istop) {
      break;
    }
    const yTrend = m * combinedXValues[si] + b;
    trendlineData.push(yTrend);
  }
  
  // Array to hold new trendlines
  const chartSeries = [];
  if (isCombinedResult) {
      jsonData.forEach(series => {
        // Add the original series to the chart series array
        chartSeries.push(series);
      });
  }
  // Add the new trendline series to the chart series array
  chartSeries.push({
    name: `Trendline`,
    data: trendlineData,
    type: 'line', // Trendlines are best represented as lines
  });

  return chartSeries;
}

// --- Example Usage ---
//const combinedTrendlineData = calculateCombinedTrendline(jsonData, true, true);
//console.log(combinedTrendlineData);

Contoh hasil

[
  {
    name: 'TRM 2025',
    data: [
      264, 322, 272, 475, 305,
      792, 542, 650,   0,   0,
        0, 114
    ],
    type: 'column'
  },
  {
    name: 'TRM 2024',
    data: [
      174, 257, 172, 338, 347,
      681, 591, 641, 208,   1,
        0,  49
    ],
    type: 'line'
  },
  {
    name: 'TRM 2023',
    data: [
      359, 126, 285, 306, 401,
      544, 623, 583, 423,  69,
        0,   3
    ],
    type: 'line'
  },
  {
    name: 'TRM 2024 Trendline',
    data: [
      299.05454545454546,
      308.3757575757576,
      317.6969696969697,
      327.0181818181818,
      336.339393939394,
      345.6606060606061,
      354.9818181818182,
      364.3030303030303,
      373.6242424242424,
      382.94545454545454
    ],
    type: 'line'
  }
]
[
  {
    name: 'TRM 2025 Trendline',
    data: [
      236.41666666666663,
      298.2261904761905,
      360.0357142857143,
      421.8452380952381,
      483.65476190476187,
      545.4642857142858,
      607.2738095238095,
      669.0833333333333
    ],
    type: 'line'
  },
  {
    name: 'TRM 2024 Trendline',
    data: [
      299.05454545454546,
      308.3757575757576,
      317.6969696969697,
      327.0181818181818,
      336.339393939394,
      345.6606060606061,
      354.9818181818182,
      364.3030303030303,
      373.6242424242424,
      382.94545454545454
    ],
    type: 'line'
  },
  {
    name: 'TRM 2023 Trendline',
    data: [
      315.9090909090909,
      328.3515151515151,
      340.79393939393935,
      353.2363636363636,
      365.67878787878783,
      378.1212121212121,
      390.56363636363636,
      403.0060606060606,
      415.44848484848484,
      427.8909090909091
    ],
    type: 'line'
  }
]
[
  {
    name: 'TRM 2025',
    data: [
      264, 322, 272, 475, 305,
      792, 542, 650,   0,   0,
        0, 114
    ],
    type: 'column'
  },
  {
    name: 'TRM 2024',
    data: [
      174, 257, 172, 338, 347,
      681, 591, 641, 208,   1,
        0,  49
    ],
    type: 'line'
  },
  {
    name: 'TRM 2023',
    data: [
      359, 126, 285, 306, 401,
      544, 623, 583, 423,  69,
        0,   3
    ],
    type: 'line'
  },
  {
    name: 'Trendline',
    data: [
      188.30555555555554,
      254.1468253968254,
      319.98809523809524,
      385.82936507936506,
      451.6706349206349,
      517.5119047619048,
      583.3531746031746,
      649.1944444444443
    ],
    type: 'line'
  }
]

By basit

Biro Pengembangan Teknologi Dan Sistem Informasi

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.