D3.js линейный сюжет панды датафрейм JSON

1

Может ли кто-нибудь дать хороший пример того, как использовать D3 для синтаксического анализа стандартного вывода python pandas dataframe to_json(), который в итоге выглядит примерно так:

"{"column1":{"2017-09-20T11:14:18.000Z":2.1,"2017-09-20T11:14:19.000Z":2.3,"2017-09-20T11:14:20.000Z":2.4}}"

В конечном счете, я ищу линейный график со временем по оси x и значение "column1" по оси y

Мне удалось что-то сделать с данными JSON в другом формате:

{"2017-09-20T11:14:18.000Z","values":["column1":2.1,"column2":3.0]}

но в идеале я бы хотел не менять формат JSON, поскольку он используется в другом месте. Извиняюсь, если я пропущу что-то очевидное, я думал, что примеров этого было бы легче найти!

Теги:
d3.js

1 ответ

1
Лучший ответ

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

Таким образом, хотя вам не нужно изменять структуру json, вы кормите скрипт, который намечает данные, сценарий, который отображает данные, должен будет создать что-то с измененной структурой.

Подобное структурирование данных часто требуется в d3, и, следовательно, в этом процессе имеется ряд вспомогательных функций d3. Рассматривая ваш примерный фреймворк, нам помогают две вспомогательные функции, помогая d3.keys() данные в d3, d3.keys() и d3.map():

d3.keys (объект) <>

Возвращает массив, содержащий имена свойств указанного объекта (ассоциативный массив). Порядок возвращаемого массива не определен.

И в d3.map() мы в основном обеспокоены map.entries():

map.entries() <>

Возвращает массив объектов с ключом для каждой записи на этой карте. Порядок возвращаемых записей произвольный. Каждый ключ ввода - это строка, но значение имеет произвольный тип.

Принимая ваш json:

{"column1":{"2017-09-20T11:14:18.000Z":2.1,"2017-09-20T11:14:19.000Z":2.3,"2017-09-20T11:14:20.000Z":2.4}}

Мы можем использовать (я добавил второй столбец для демонстрации):

var df = {"column1":{"2017-09-20T11:14:18.000Z":2.1,"2017-09-20T11:14:19.000Z":2.3,"2017-09-20T11:14:20.000Z":2.4},
"column2":{"2017-09-20T11:14:18.000Z":2.3,"2017-09-20T11:14:19.000Z":2.1,"2017-09-20T11:14:20.000Z":2.2}};
	
var dataSeries = d3.keys(df);  // get each column
var dataArray = [];            // the data array that we will plot
	
dataSeries.forEach(function(d) {
	dataArray.push(d3.map(df[d]).entries()); // get each key value pair and return as an object
	})
	
console.log(dataArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>

Это выводит массив, содержащий каждую серию. Каждая серия содержит объект сопряжения ключевых значений, который мы можем использовать для построения данных. Это позволит графически отобразить данные относительно прямолинейно, и в этой структуре данных также должно быть много примеров, чтобы помочь.

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

Простой граф с использованием этого метода может выглядеть так:

var width = 500, height = 200;

////////////// structure data

var df = {"column1":{"2017-09-20T11:14:18.000Z":2.1,"2017-09-20T11:14:19.000Z":2.3,"2017-09-20T11:14:20.000Z":2.4},
"column2":{"2017-09-20T11:14:18.000Z":2.3,"2017-09-20T11:14:19.000Z":2.1,"2017-09-20T11:14:20.000Z":2.2}};
	
var dataSeries = d3.keys(df);
var dataArray = [];
	
dataSeries.forEach(function(d) {
	dataArray.push(d3.map(df[d]).entries()); // get each key value pair and return as an object
})

////////////// scale and draw data

var timeParse = d3.utcParse("%Y-%m-%dT%H:%M:%S.%LZ");
	
var x = d3.scaleTime()
	  .domain(d3.extent(dataArray[0], function(d) { return timeParse(d.key); }) )
	  .range([0,width]);
	  
	var y = d3.scaleLinear()
	  .domain(d3.extent(dataArray[0], function(d) { return d.value; }) )
	  .range([0,height])
	  
	var line = d3.line()
	  .x(function(d) {return x(timeParse(d.key)); })
	  .y(function(d) { return y(d.value); })
	  
	var svg = d3.select("body")
	  .append("svg")
	  .attr("width",width)
	  .attr("height",height);
	  
	svg.selectAll(null)
	  .data(dataArray)
	  .enter()
	  .append("path")
	  .attr("d",line)
	  .attr("stroke", function(d,i) { return ["steelblue","orange"][i]; })
	  .attr("stroke-width",2)
	  .attr("fill","none");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>

Примечание. Я масштабировал данные только в соответствии с первым столбцом в фрейме данных

  • 0
    Спасибо, отличный ответ!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню