Предваряя это тем фактом, что я новичок в D3, и, вероятно, это простая ошибка, которую я упускаю - я знаю, что это должно быть. Что-то в том, как я пытаюсь получить доступ к данным.
Пытаюсь понять этого парня какое-то время. (возможно, я смотрел на это слишком долго)
Я играл с ним, пока моя строка наконец не появилась вообще, но теперь она отображает не всю строку, а только две точки - это числа, в которых я не уверен.
Заранее спасибо!
Обновлено: Цель состоит в том, чтобы использовать lineData [0] для построения одной линии по оси x lineData1 (месяцев). В конце концов, lineData2 будет использоваться для второй строки, но просто пытается заставить работать первую строку в данный момент.
Обновлено: обновленный код (согласно предложениям Шашанка) можно найти здесь: https://codepen.io/anon/pen/RevxYG?editors=0010
Мой обновленный график выглядит лучше, но все еще видны значения NaN:

Вот мой код:
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
console.info("lineData", lineData)
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 52])
.range([height - 40 , 0]);
let xScale = d3.scaleOrdinal()
.range([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d[0]); });
// create svg container
let lineChart = d3.select(element)
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
lineChart.append("path")
.datum(lineData)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
lineChart.selectAll("dot")
.data(lineData)
.attr("d", line)
.enter()
.append("circle")
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(i)})
.attr("cy", function(d) { return yScale(d[0])})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
Данные передаются через функцию.
Не могли бы вы включить свои данные вместо img?
@MikeTung Я думал, порядковые шкалы подойдут, не так ли?
@mahan да, одна секунда. Отредактировал это
Требуются пояснения: 1. Вы пытаетесь построить 1 линию, используя lineData[0] (массив из 12 чисел), и 12 кругов, используя lineData[1] (массив из 12 чисел)? 2. Или вы пытаетесь построить 2 линии на основе lineData[0] и lineData[1] и круги соответственно? (учитывая месяцы в lineData[2] как xAxis в обоих вышеупомянутых случаях). Это потому, что вы привязываете lineData к кругам вместе с вызовом .attr('d', line) для кругов, что сбивает с толку.
@Shashank пытается построить 1 строку, используя lineData [0] (массив из 12 чисел) В конце концов, используя 2-й массив для построения второй строки (просто пытаясь заставить первую строку работать)
Хорошо. Понятно. Спасибо.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Недостающие точки:
Band scales are like ordinal scales except the output range is continuous and numeric.
Почему бы не использовать d3.scaleOrdinal? Вот пример:
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
let xScale = d3.scaleOrdinal().range(lineData[2])
.domain(lineData[0]);
console.info('domain is: ' + xScale.domain());
console.info('range is: ' + xScale.range());<script src = "https://d3js.org/d3.v4.min.js"></script>Вы видите, как повторяющиеся значения сопоставляются с месяцами, которые не помогут в вашем случае, и поэтому d3.scaleBand() (вы также можете поиграть с использованием d3.scalePoint. Подробнее об этом читайте в этом ответе.
Используя указанную выше шкалу, вы зададите домен lineData[2] следующим образом:
xScale = d3.scaleBand().domain(lineData[2])
Преобразования не применялись к line и circles. Поэтому я добавил контейнеры <g>, чтобы они содержали линии и круги соответственно, и преобразовал эти элементы группы. Например:
var dots = lineChart.append('g')
.attr("transform", "translate(20, 0)");
Приведенное ниже решение просто отвечает на этот конкретный вопрос о добавлении первой строки к диаграмме. Как вы упомянули в комментариях, что в конечном итоге вы будете работать над добавлением второго элемента в качестве другой строки, выбор path изменится
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 52])
.range([height - 40 , 0]);
let xScale = d3.scaleBand().domain(lineData[2])
.rangeRound([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) {
return xScale(lineData[2][i]) + xScale.bandwidth()/2;
})
.y(function(d) { return yScale(d); });
// create svg container
let lineChart = d3.select('body')
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
var lineG = lineChart.append('g')
.attr("transform", "translate(20, 0)");
lineG.append("path")
.data(lineData)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
var dots = lineChart.append('g')
.attr("transform", "translate(20, 0)");
dots.selectAll("dot")
.data(lineData[0])
.enter()
.append("circle").classed('dot', true)
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(lineData[2][i]) + xScale.bandwidth()/2})
.attr("cy", function(d) { return yScale(d)})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))<script src = "https://d3js.org/d3.v4.min.js"></script>Предложение: не рекомендуется устанавливать для домена статическое значение, как это делается для yScale [0,52]. Попробуйте использовать методы d3.extent или d3.min.
Надеюсь это поможет.
Редактировать: Когда вы пытаетесь использовать d3.scalePoint, вы делаете небольшую ошибку, выбирая значение xScale в функции line и для кругов. Вам нужно будет выбрать categories[i] в строке fn следующим образом:
.x(function(d, i) {
return xScale(categories[i]);
})
Обновлен фрагмент с использованием d3.scalePoint
let data = {
'New': [4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
'Terminated': [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]
};
let categories = ["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"];
let lineData = [data.New, data.Terminated, categories];
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 60]).nice()
.range([height - 40 , 0]);
let xScale = d3.scalePoint()
.domain(lineData[2].map(function(d, i) { return d; }))
.range([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) {
return xScale(categories[i]);
})
.y(function(d) { return yScale(d); });
// create svg container
let lineChart = d3.select('body')
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
var lineG = lineChart.append('g')
.attr("transform", "translate(20, 0)");
lineG.append("path")
.datum(lineData)
.attr("d", function(d) { return line(d[0]); })
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
lineChart.selectAll("dot")
.data(lineData[0])
.enter()
.append("circle")
.attr("transform", "translate(20, 0)")
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(categories[i])})
.attr("cy", function(d) { return yScale(d)})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))<script src = "https://d3js.org/d3.v4.min.js"></script>Надеюсь, это тоже поможет.
Это очень полезно! Пара вещей. Шкала времени показала действительно странные результаты. Я хотел придерживаться порядкового номера, потому что это строка; тем не мение; Я обнаружил, что scalePoint делает именно то, что мне нужно! Я попытался внести некоторые изменения, но график сломался. С некоторыми изменениями, которые я внес, теперь график выглядит лучше, но я все еще вижу значения NaN для некоторых данных. Вы можете увидеть мой обновленный код здесь: codepen.io/anon/pen/RevxYG?editors=0010. Я добавлю эту ссылку и обновленное изображение в свой OP
это на самом деле идеально, я пошел по вашему маршруту вместо scalePoint. Спасибо еще раз!
@Almost_Ashleigh Обновил пост реализацией с использованием d3.scalePoint (если вам все еще интересно узнать, как это сработает). Рад, что смог помочь! :)
Вы можете уточнить, в чем проблема? У вас есть даты в вашем наборе данных, и вам нужно будет применить timeScale, чтобы получить фактические координаты X, Y