Распределение точек (подсчет частоты) - PullRequest
2 голосов
/ 15 октября 2019

Я пытаюсь воспроизвести гистограмму, состоящую из точек. Вот хорошая ссылка:

enter image description here

Мои данные имеют следующий формат:

{'name':'Company1', 'aum':42, 'growth':16},
{'name':'Company2', 'aum':36, 'growth':24},
{'name':'Company3', 'aum':34, 'growth':19},
...

В моем случае я беннингна aum и цветовое кодирование growth. Все казалось нормальным, пока я не установил атрибут cy.

graphGroup.selectAll('circ')
    .data(data)
    .enter()
    .append('circ')
    .attr('r',8)
    .attr('cx', function(d) { return xScale(d.aum);})
    .attr('cy', ??????)
    .style('fill', function(d) { return colorScale(d.growth);});

Единственный способ справиться с этим - перестроить данные, чтобы дать им явное значение индекса y иличто-то. Тем не менее, это не поддерживается в моем наборе статистики, и n слишком велик, чтобы я мог это сделать вручную.

Вопрос

Учитывая мою текущую структуру данных, может ли d3 помочь мне с чем-либоСпециально, чтобы получить правильное значение у? Я думал, что счетчик может сработать, но я не смог придумать счетчик для бина. Возможно, у d3 есть более элегантное решение, чем у счетчика.

1 Ответ

1 голос
/ 15 октября 2019

... может ли d3 помочь мне с чем-то специальным образом получить правильное значение y?

Нет, для этого нет собственного метода. Но здесь большинство людей ошибаются в D3: D3 - это не инструмент построения диаграмм (за исключением модуля оси, D3 ничего не рисует!), Это просто набор методов JavaScript. Этот факт одновременно дает D3 его слабость (крутая кривая обучения) и его преимущество (с D3 вы можете сделать почти все).

В вашем случае, например, все, что я хотел бы сделать, это разделить данные в бункерах (используя генератор гистограмм, например, или просто напрямую манипулируя данными), а затем добавляя кружки в каждую ячейку / группу, используя их индексы .

Это может быть что-то вроде этого:

circle.attr("cy", function(_, i) {
    return maxValue - circleRadius * i;
});

Это добавит первый кружок каждого бина (группы) в основании SVG, а затем каждый последующий в меньшую y координату, в соответствии с его индексом.

Проверьте это основное демо:

const data = d3.range(100).map(() => Math.random());
const svg = d3.select("svg");
const xScale = d3.scalePoint(d3.range(10).map(d => d / 10), [20, 480])
  .padding(0.5);
const binData = d3.histogram()
  .domain([0, 1])(data);
const g = svg.selectAll(null)
  .data(binData)
  .enter()
  .append("g")
  .attr("transform", d => "translate(" + xScale(~~(100 * d.x0) / 100) + ",0)");
g.selectAll(null)
  .data(d => d)
  .enter()
  .append("circle")
  .attr("r", 5)
  .attr("cy", function(_, i) {
    return 220 - 13 * i;
  })
  .style("fill", "gray")
  .style("stroke", "black");
const axisGroup = svg.append("g")
  .attr("transform", "translate(0,230)")
  .call(d3.axisBottom(xScale));
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="500" height="250"></svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...