d3js переключение между несколькими диаграммами

#javascript #json #d3.js #data-visualization

#javascript #json #d3.js #визуализация данных

Вопрос:

Обучаясь самостоятельно и будучи новичком в D3.js , Я пытаюсь создать несколько круговых диаграмм с разными категориями, переключаемыми пользовательскими кнопками.

Я создал отдельную круговую диаграмму с эффектом: https://bl.ocks.org/lydiawawa/7c385eaaf24cb4e6047c9b56866fac6e/252dfbf9f27123e5577f6c54ca7dffe6fd75714e

Я надеюсь добиться следующего эффекта с помощью всплывающей подсказки и метки, но вместо orange и apple я хотел бы переключаться между полом, возрастом и расой:

Желаемый эффект: http://bl.ocks.org/j0hnsmith/5591116

Это то, что у меня есть до сих пор: https://blockbuilder.org/lydiawawa/38243015ab2ac96b6086d3bae56572b9

Самая сложная часть — преобразование круговой диаграммы с двумя категориями в три категории с добавлением всплывающей подсказки и метки. Я хотел бы получить некоторую помощь в достижении эффекта. Спасибо за любой вклад!

Редактировать

Недавно я обнаружил следующий эффект с тремя категориями, но я не знаю, как добавить метку или легенду к графику, которые позже можно использовать и для всплывающей подсказки:

http://bl.ocks.org/jfreels/6919598

Я попытался изменить формат json в следующем формате. Может быть, таким образом мы можем использовать d3.json вместо init()?

 [
 {
   "genderC": "female",
   "gender": 533,
   "raceC": "A",
   "race": 20,
   "ageC": "0 < 12 years",
   "age": 8
 },
 {
   "genderC": "male",
   "gender": 260,
   "raceC": "A E",
   "race": 19,
   "ageC": "13 years",
   "age": 1
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "A D",
   "race": 2,
   "ageC": "14 years",
   "age": 102
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "A DE",
   "race": 1,
   "ageC": "15 years",
   "age": 195
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "A C",
   "race": 5,
   "ageC": "16 years",
   "age": 200
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "A C E",
   "race": 5,
   "ageC": "17 years",
   "age": 187
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "AB D",
   "race": 1,
   "ageC": "18 years",
   "age": 100
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "ABC E",
   "race": 1,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "ABCD",
   "race": 1,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "ABCDE",
   "race": 1,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "B",
   "race": 27,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "B H",
   "race": 0,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "B E",
   "race": 6,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "B D",
   "race": 6,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "B DE",
   "race": 2,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "BC",
   "race": 2,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "BCD",
   "race": 1,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "C",
   "race": 175,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "C E",
   "race": 17,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "CD",
   "race": 3,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "D",
   "race": 14,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "DE",
   "race": 3,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "E",
   "race": 481,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 },
 {
   "genderC": "",
   "gender": null,
   "raceC": "",
   "race": null,
   "ageC": "",
   "age": null
 }
]
 

Комментарии:

1. Я просматриваю blockbuilder, которым вы поделились, и я немного сбит с толку, каковы ваши окончательные данные? В blockbuilder у вас есть ваши данные в dataset.json, но это просто javascript, поскольку у вас есть массивы объектов var gender = [{..}],{..}] . Если ваши данные уже представлены в виде массивов объектов, вам не нужно создавать json. Иметь их в качестве отдельных переменных на самом деле проще.

2. @Coola Я импортировал json в виде скрипта в index.html и массивы были вызваны в init() . Вы имеете в виду, что мне не нужно вызывать его index.html ? Я могу просто определить массивы в PieChart()?

3. @Coola Я думаю, что я надеюсь просто использовать свой собственный набор данных для создания трех круговых диаграмм, переключаемых кнопками. Переход будет иметь эффект от этого примера: bl.ocks.org/j0hnsmith/5591116 с надписью или меткой, обозначающей цвета. Эффект всплывающей подсказки также будет добавлен для отображения процента.

4. Да, вы можете просто определить массивы внутри main.js . Я понимаю, чего бы вы хотели, но копирование кода из других источников без понимания того, что они делают, приводит к тому, что ваш текущий блок немного запутывается.

5. @Coola Я переместил эти переменные в init() в main.js . Код обновляется.

Ответ №1:

В вашем коде было несколько проблем, и мне пришлось внести несколько изменений.

Если я правильно понимаю, основная идея для вас заключалась в том, чтобы перерисовать круговые диаграммы в зависимости от того, на какие данные нажимает пользователь, например, «Пол», «Возраст» или «Раса».

  1. Данные для каждого из них очень разные, то есть разные пары ключ-значение объекта. Я сделал все count ключи одинаковыми (в наборе данных age они были Count ).
  2. Поскольку данные сильно отличаются друг от друга, примеры, которые вы показываете, когда данные обновляются, могут здесь не применяться, поскольку в этом случае данные не преобразуются. Вместо этого подход, который я использовал, состоял в том, чтобы просто очистить div и перерисовать круговую диаграмму. Итак, первое, что он делает, это очищает область диаграммы, а затем начинает рисовать. Это значительно сокращает объем необходимого кода (ваш main.js = > 300 строк, тогда как у меня 138 строк)
  3. Я улучшил всплывающую подсказку по мере изменения ваших ключей данных, поэтому это необходимо учитывать во всплывающей подсказке.
  4. Я переместил ваши данные в отдельный js-файл, чтобы не загромождать main.js . Я просто обязательно вызываю это перед main.js в index.html досье.
  5. Я обновил function color(d) функцию, чтобы выбирать цвета из массива объектов на основе ключей данных. Вы можете расширить массив в соответствии с вашими потребностями. Если вы хотите использовать цвета в пределах диапазона, вы можете использовать var color = d3.scale.category20(); и вызывать цвет, используя индекс данных .attr("fill", function (d, i) { return color(i);}) , как показано в этом примере http://bl.ocks.org/j0hnsmith/5591116

Вот рабочий блок https://bl.ocks.org/akulmehta/923f277f8a10d0c35b77f6e3a84929bf /

Обратите внимание, что, поскольку много точек данных для age и race есть 0 , анимация немного заикается. Также обратите внимание, что ваши метки перекрываются, когда дуги расположены очень близко друг к другу. Поэтому я бы предложил удалить метки.

Комментарии:

1. Спасибо вам за все. Вы даже выбрали цвета для категориальной переменной. Я рассмотрю / изучу код и внесу некоторые изменения, как только вернусь домой сегодня.

2. Я приму ответ, как только вернусь домой, мое приложение по какой-то причине не позволяет мне отмечать проверку.

3. Я попытался внести несколько изменений в ваш отредактированный код. Я добавил условия в оператор else для цветов, которые определяли бы категории расы, но график гонки не появился после изменения. Я также пытался добавить легенду к графику после удаления меток, но легенда тоже не появляется. Это старая ссылка с моими обновлениями: blockbuilder.org/lydiawawa/38243015ab2ac96b6086d3bae56572b9

4. Я приму ответ сейчас, но не могли бы вы помочь сделать последние несколько дополнений. Я думаю, что я довольно близок, но по какой-то причине эффекты не отображаются.

5. Как насчет этого blockbuilder.org/akulmehta/1aa16d77c876b213d982c54a8e86e434 ? При вызове функции color в функцию передается дополнительная информация, чтобы сообщить ей, какой это тип данных и длина данных. Делая это, вы можете использовать его для использования порядковых шкал для получения значения цвета. Надеюсь, это поможет.