Я пытаюсь создать многострочный график с d3. Я могу манипулировать своими данными в любом формате в контроллере и передавать его на график, но не уверен, что такое формат по умолчанию или наилучшая практика, которую принимает d3. примеры очень разные и работают с разными формами записей различными способами, такими как:
считыватели файлов:
csv()
tsv()
col1,col2,col3
x1,y1,y2,...
x2,y1,y2,...
или массив объектов:
[
{key:"col1",value:[[x1,y1],[x2,y2],...]},
{key:"col2",value:[[x1,y1],[x2,y2],...]},
]
или же
[
{ label: "col1",
x: [x1, x2, x3,...],
y: [y1, y2, y3,...] },
{ label: "col2",
x: [x1, x2, x3,...],
y: [y1, y2, y3,...] }
] ;
и так много других форматов...
Но в основном я ищу формат по умолчанию, который я могу передавать многосерийным данным на d3 с меньшим количеством манипуляций с данными в кодах диаграмм. Я хочу только передать подготовленные данные в d3.
Вместо того, чтобы отвечать "какой формат загрузки по умолчанию для нескольких строк в d3?", Который довольно неопределен и четко основан на мнениях (поскольку формат по умолчанию отсутствует), я просто объясню некоторые базовые принципы D3 для объединения данных.
Метод данных (selection.data()
) принимает 3 вещи:
Итак, мы будем использовать массив для хранения данных для многострочной.
И теперь идет важная часть: сам генератор строк использует массив для рисования путей. Согласно API, d3.line:
Создает строку для данного массива данных.
Поэтому это самый простой формат для многострочного:
[//outer array
[...],
[...],
[...]
//inner arrays, one for each line
]//closing the outer array
Эти внутренние массивы могут содержать объекты или даже другие массивы (с двумя значениями каждый, один для позиции x
а другой для позиции y
).
Например, внутренние массивы, содержащие объекты:
var data = [
[{x:0, y: 0},{x:50, y: 40},{x:100, y: 100},{x:150, y: 90},{x:200, y: 150}],
[{x:0, y: 50},{x:50, y: 60},{x:100, y: 100},{x:150, y: 110},{x:200, y: 10}],
[{x:0, y: 20},{x:50, y: 20},{x:100, y: 140},{x:150, y: 130},{x:200, y: 10}]
];
И содержащие массивы:
var data = [
[[0, 10],[50, 20],[100, 30]],
[[0, 80],[50, 10],[100, 40]],
[[0, 50],[50, 120],[100, 90]]
];
Поскольку это один из простейших форматов, он может вам подойдет, поскольку вы сказали: "Я ищу формат по умолчанию, который я могу передавать многосерийным данным на d3 с меньшим количеством манипуляций с данными".
Вам просто нужно создать выбор ввода, например:
var lines = svg.selectAll(null)
.data(data)
.enter()
.append("path")
.attr("d", lineGenerator)
Количество строк (путей) - это количество внутренних массивов. Для каждой строки (пути) соответствующий внутренний массив передается как данные.
Вот демонстрация:
var data = [
[{x:0, y: 0},{x:50, y: 40},{x:100, y: 100},{x:150, y: 90},{x:200, y: 150},{x:250, y: 140},{x:300, y: 130}],
[{x:0, y: 120},{x:50, y: 60},{x:100, y: 100},{x:150, y: 110},{x:200, y: 90},{x:250, y: 10},{x:300, y: 30}],
[{x:0, y: 20},{x:50, y: 20},{x:100, y: 140},{x:150, y: 130},{x:200, y: 10},{x:250, y: 70},{x:300, y: 90}]
];
var svg = d3.select("svg");
var color = d3.scaleOrdinal(d3.schemeCategory10)
var lineGenerator = d3.line()
.x(function(d) {
return d.x
})
.y(function(d) {
return d.y
})
var lines = svg.selectAll(null)
.data(data)
.enter()
.append("path")
.attr("d", lineGenerator)
.attr("fill", "none")
.attr("stroke-width", 3)
.attr("stroke", function(d, i) {
return color(i)
})
svg {
border: 1px solid darkgray;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
И как люди создают эти вложенные массивы на основе данных (например, CSV или TSV)? Это другой вопрос. Наиболее распространенный способ (но не единственный), как предлагается в комментариях, использует d3.nest()
.
null
в svg.selectAll(null)
?
[{x: 1; y: 2; group: A}, {x:2; y: 4; group: B}...]
, вложите данные с любыми ключами (group by) и нарисуйте линии из вложенного объекта данных.