Строка D3.js возвращает случайное число

Предваряя это тем фактом, что я новичок в D3, и, вероятно, это простая ошибка, которую я упускаю - я знаю, что это должно быть. Что-то в том, как я пытаюсь получить доступ к данным.

Пытаюсь понять этого парня какое-то время. (возможно, я смотрел на это слишком долго)

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

Заранее спасибо!

Обновлено: Цель состоит в том, чтобы использовать lineData [0] для построения одной линии по оси x lineData1 (месяцев). В конце концов, lineData2 будет использоваться для второй строки, но просто пытается заставить работать первую строку в данный момент.

Обновлено: обновленный код (согласно предложениям Шашанка) можно найти здесь: https://codepen.io/anon/pen/RevxYG?editors=0010

Мой обновленный график выглядит лучше, но все еще видны значения NaN: Строка D3.js возвращает случайное число

Вот мой код:

 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))

Данные передаются через функцию.

данные: Строка D3.js возвращает случайное число

и моя диаграмма выглядит так: Строка D3.js возвращает случайное число

и мой генерируемый путь / точки выглядят так: Строка D3.js возвращает случайное число

Вы можете уточнить, в чем проблема? У вас есть даты в вашем наборе данных, и вам нужно будет применить timeScale, чтобы получить фактические координаты X, Y

Mike Tung 26.10.2018 14:56

Не могли бы вы включить свои данные вместо img?

mahan 26.10.2018 14:56

@MikeTung Я думал, порядковые шкалы подойдут, не так ли?

Almost_Ashleigh 26.10.2018 14:58

@mahan да, одна секунда. Отредактировал это

Almost_Ashleigh 26.10.2018 14:58

Требуются пояснения: 1. Вы пытаетесь построить 1 линию, используя lineData[0] (массив из 12 чисел), и 12 кругов, используя lineData[1] (массив из 12 чисел)? 2. Или вы пытаетесь построить 2 линии на основе lineData[0] и lineData[1] и круги соответственно? (учитывая месяцы в lineData[2] как xAxis в обоих вышеупомянутых случаях). Это потому, что вы привязываете lineData к кругам вместе с вызовом .attr('d', line) для кругов, что сбивает с толку.

Shashank 26.10.2018 15:18

@Shashank пытается построить 1 строку, используя lineData [0] (массив из 12 чисел) В конце концов, используя 2-й массив для построения второй строки (просто пытаясь заставить первую строку работать)

Almost_Ashleigh 26.10.2018 15:20

Хорошо. Понятно. Спасибо.

Shashank 26.10.2018 15:21
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
7
152
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Недостающие точки:

  1. Важно: в идеале вы должны использовать шкала времени d3, поскольку вы хотите построить линию на основе месяцев. Но порядковая шкала тоже подойдет. Полагаю, вы ищете здесь d3.scaleBand.

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. Подробнее об этом читайте в этом ответе.

  1. Используя указанную выше шкалу, вы зададите домен lineData[2] следующим образом:

    xScale = d3.scaleBand().domain(lineData[2])
    
  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

Almost_Ashleigh 26.10.2018 17:06

это на самом деле идеально, я пошел по вашему маршруту вместо scalePoint. Спасибо еще раз!

Almost_Ashleigh 26.10.2018 17:25

@Almost_Ashleigh Обновил пост реализацией с использованием d3.scalePoint (если вам все еще интересно узнать, как это сработает). Рад, что смог помочь! :)

Shashank 26.10.2018 17:29

Другие вопросы по теме