Как сгруппировать меньшие фрагменты диаграммы P ie, чтобы улучшить читаемость в чартах - PullRequest
0 голосов
/ 14 апреля 2020

Я хотел бы сгруппировать данные, которые находятся под определенным порогом, скажем, 10%, в один срез, называемый другими. Как бы я go об этом на графике js?

Обратите внимание, что во фрагменте отображается только первый набор данных (ADVERTS_PUBLISHED), но диаграмму можно обновить любым из них на реальной странице.

var ctx = document.getElementById('myChart').getContext('2d');

var labels = ["Caterer", "INDEED", "Sarova Website", "Send to Friend", "alexandre-creed.com", "amdas.co.uk", "catabaseuk.co.uk", "cerecruit.co.uk", "el8recruitment.com", "equinoxresourcing.co.uk", "gatewayjobs.co.uk", "hotelstaffpec.co.uk", "jwrecruitment.co.uk", "marshallhr.co.uk", "marshallhr.com (Sarova)", "momentumrecruitment.com", "peoplebank.com", "ph-recruitment.co.uk", "platinum-hospitality.co.uk", "q", "talenthive.co.uk", "towngate-personnel.co.uk"];

var dataSet = {
  "ADVERTS_PUBLISHED": ["102", "130", "153", "2", "2", "2", "2", "4", "2", "5", "2", "4", "3", "8", "4", "4", "4", "1", "3", "4", "1", "2"],
  "VIEWS": ["1642", "10566", "45269", "7", "4", "1", "11", "9", "11", "12", "5", "0", "14", "6", "3", "13", "19", "2", "8", "3", "2", "2"],
  "CLICKS": ["1992", "3628", "4458", "4", "2", "2", "7", "3", "11", "5", "6", "9", "10", "15", "10", "4", "34", "10", "10", "3", "0", "8"],
  "SUBMITTED": ["1101", "877", "1290", "2", "3", "2", "10", "14", "11", "5", "5", "7", "6", "14", "8", "6", "17", "7", "9", "4", "1", "6"],
  "PENDING": ["115", "26", "93", "0", "1", "0", "7", "3", "6", "2", "0", "0", "4", "8", "0", "3", "0", "0", "1", "0", "1", "0"],
  "FILTERED": ["546", "493", "764", "1", "2", "2", "9", "12", "10", "5", "4", "5", "5", "12", "2", "3", "4", "6", "4", "0", "1", "5"],
  "SHORTLISTED": ["37", "23", "32", "1", "0", "0", "0", "1", "0", "2", "0", "1", "0", "5", "0", "0", "0", "0", "2", "0", "0", "1"],
  "REGRETTED": ["103", "28", "52", "0", "1", "0", "1", "6", "5", "3", "0", "2", "1", "1", "0", "0", "1", "3", "1", "0", "0", "2"],
  "INTERVIEWED": ["62", "45", "88", "0", "0", "0", "1", "2", "2", "2", "0", "3", "0", "3", "0", "2", "0", "4", "0", "0", "0", "1"],
  "OFFERED": ["4", "10", "20", "0", "0", "0", "0", "0", "0", "0", "0", "3", "0", "2", "0", "0", "0", "0", "0", "0", "0", "0"],
  "OFFERED_AND_DECLINED": ["0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"],
  "REGRETTED_AND_COMM": ["587", "334", "533", "0", "0", "2", "1", "1", "2", "1", "0", "1", "2", "4", "0", "1", "0", "0", "0", "2", "0", "0"],
  "ACTUAL_HIRED": ["4", "2", "8", "0", "0", "0", "0", "0", "0", "0", "0", "2", "0", "1", "0", "0", "0", "0", "0", "0", "0", "0"]
};

var colors = [];
labels.forEach((element) => {
  var hex_color = getRandomColorHex();
  colors.push(hex_color);
});

function getRandomColorHex() {
  var hex = "0123456789ABCDEF",
    color = "#";
  for (var i = 1; i <= 6; i++) {
    color += hex[Math.floor(Math.random() * 16)];
  }
  return color;
}



myChart = new Chart(ctx, {
  type: 'pie',
  data: {
    labels: labels,
    datasets: [{

      data: dataSet.ADVERTS_PUBLISHED,
      backgroundColor: colors,
      borderWidth: 1
    }]
  },
  options: {
    responsive: true,
    maintainAspectRatio: true,

    hover: {
      onHover: function(e, el) {
        $("#myChart").css("cursor", e[0] ? "pointer" : "default");
      }
    },
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true,
          autoSkip: true
        }
      }]
    },
    title: {
      display: true,
      text: 'Adverts Published'
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div>
  <canvas class="chart__graph" id="myChart"></canvas>
</div>

1 Ответ

0 голосов
/ 15 апреля 2020

Следующий код вычисляет массив с именем slices, который содержит объекты со свойствами label и value для всех срезов p ie, которые будут включены в диаграмму. Все значения ниже 1 процента суммируются и удерживаются объектом, помеченным «Другие».

В этом коде используются удобные методы Array, такие как reduce(), map(), find(), concat() и push().

const values = dataSet.ADVERTS_PUBLISHED.map(v => Number(v));
const valueSum = values.reduce((a, b) => a + b, 0);
const thresholdPercent = 1;
const slices = values.map((v, i) => ({ label: labels[i], value: v }))
  .reduce((accumulator, currObj) => {
    const percent = 100 * currObj.value / valueSum;
    if (percent < thresholdPercent) {
      const others = accumulator.find(o => o.label == 'Others');
      if (!others) {
        return accumulator.concat({ label: 'Others', value: currObj.value });
      }
      others.value += currObj.value;
    } else {
      accumulator.push(currObj);
    }
    return accumulator;
  }, []);

С Из массива slices я извлекаю массивы меток и значений и присваиваю их data.labels и data.datasets[0].data конфигурации диаграммы следующим образом:

data: {
  labels: slices.map(o => o.label),
  datasets: [{
    data: slices.map(o => o.value),

Пожалуйста, взгляните на ваш исправленный код ниже:

var labels = ["Caterer", "INDEED", "Sarova Website", "Send to Friend", "alexandre-creed.com", "amdas.co.uk", "catabaseuk.co.uk", "cerecruit.co.uk", "el8recruitment.com", "equinoxresourcing.co.uk", "gatewayjobs.co.uk", "hotelstaffpec.co.uk", "jwrecruitment.co.uk", "marshallhr.co.uk", "marshallhr.com (Sarova)", "momentumrecruitment.com", "peoplebank.com", "ph-recruitment.co.uk", "platinum-hospitality.co.uk", "q", "talenthive.co.uk", "towngate-personnel.co.uk"];

var dataSet = {
  "ADVERTS_PUBLISHED": ["102", "130", "153", "2", "2", "2", "2", "4", "2", "5", "2", "4", "3", "8", "4", "4", "4", "1", "3", "4", "1", "2"],
  "VIEWS": ["1642", "10566", "45269", "7", "4", "1", "11", "9", "11", "12", "5", "0", "14", "6", "3", "13", "19", "2", "8", "3", "2", "2"],
  "CLICKS": ["1992", "3628", "4458", "4", "2", "2", "7", "3", "11", "5", "6", "9", "10", "15", "10", "4", "34", "10", "10", "3", "0", "8"],
  "SUBMITTED": ["1101", "877", "1290", "2", "3", "2", "10", "14", "11", "5", "5", "7", "6", "14", "8", "6", "17", "7", "9", "4", "1", "6"],
  "PENDING": ["115", "26", "93", "0", "1", "0", "7", "3", "6", "2", "0", "0", "4", "8", "0", "3", "0", "0", "1", "0", "1", "0"],
  "FILTERED": ["546", "493", "764", "1", "2", "2", "9", "12", "10", "5", "4", "5", "5", "12", "2", "3", "4", "6", "4", "0", "1", "5"],
  "SHORTLISTED": ["37", "23", "32", "1", "0", "0", "0", "1", "0", "2", "0", "1", "0", "5", "0", "0", "0", "0", "2", "0", "0", "1"],
  "REGRETTED": ["103", "28", "52", "0", "1", "0", "1", "6", "5", "3", "0", "2", "1", "1", "0", "0", "1", "3", "1", "0", "0", "2"],
  "INTERVIEWED": ["62", "45", "88", "0", "0", "0", "1", "2", "2", "2", "0", "3", "0", "3", "0", "2", "0", "4", "0", "0", "0", "1"],
  "OFFERED": ["4", "10", "20", "0", "0", "0", "0", "0", "0", "0", "0", "3", "0", "2", "0", "0", "0", "0", "0", "0", "0", "0"],
  "OFFERED_AND_DECLINED": ["0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"],
  "REGRETTED_AND_COMM": ["587", "334", "533", "0", "0", "2", "1", "1", "2", "1", "0", "1", "2", "4", "0", "1", "0", "0", "0", "2", "0", "0"],
  "ACTUAL_HIRED": ["4", "2", "8", "0", "0", "0", "0", "0", "0", "0", "0", "2", "0", "1", "0", "0", "0", "0", "0", "0", "0", "0"]
};

var colors = [];
labels.forEach((element) => {
  var hex_color = getRandomColorHex();
  colors.push(hex_color);
});

function getRandomColorHex() {
  var hex = "0123456789ABCDEF",
    color = "#";
  for (var i = 1; i <= 6; i++) {
    color += hex[Math.floor(Math.random() * 16)];
  }
  return color;
}

const values = dataSet.ADVERTS_PUBLISHED.map(v => Number(v));
const valueSum = values.reduce((a, b) => a + b, 0);
const thresholdPercent = 1;
const slices = values.map((v, i) => ({ label: labels[i], value: v }))
  .reduce((accumulator, currObj) => {
    const percent = 100 * currObj.value / valueSum;
    if (percent < thresholdPercent) {
      const others = accumulator.find(o => o.label == 'Others');
      if (!others) {
        return accumulator.concat({ label: 'Others', value: currObj.value });
      }
      others.value += currObj.value;
    } else {
      accumulator.push(currObj);
    }
    return accumulator;
  }, []);

myChart = new Chart(document.getElementById('myChart'), {
  type: 'pie',
  data: {
    labels: slices.map(o => o.label),
    datasets: [{
      data: slices.map(o => o.value),
      backgroundColor: colors,
      borderWidth: 1
    }]
  },
  options: {
    responsive: true,
    maintainAspectRatio: true,
    hover: {
      onHover: function(e, el) {
        $("#myChart").css("cursor", e[0] ? "pointer" : "default");
      }
    },
    title: {
      display: true,
      text: 'Adverts Published'
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<div>
  <canvas class="chart__graph" id="myChart"></canvas>
</div>
...