Да. Сначала я бы реструктурировал ваши данные для более легкой итерации, например:
var series = [
[{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 8}],
[{time: 1, value: 5}, {time: 2, value: 9}, {time: 3, value: 12}],
[{time: 1, value: 3}, {time: 2, value: 2}, {time: 3, value: 2}],
[{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 15}]
];
Теперь вам нужна только одна общая строка:
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.time); })
.y(function(d) { return y(d.value); });
И затем вы можете добавить все элементы пути за один раз:
group.selectAll(".line")
.data(series)
.enter().append("path")
.attr("class", "line")
.attr("d", line);
Если вы хотите уменьшить формат структуры данных, вы также можете извлечь время в отдельный массив, а затем использовать двумерный массив для значений. Это будет выглядеть так:
var times = [1, 2, 3];
var values = [
[2, 4, 8],
[5, 9, 12],
[3, 2, 2],
[2, 4, 15]
];
Поскольку матрица не включает значение времени, вам нужно найти его из x-аксессора генератора строки. С другой стороны, y-аксессор упрощен, поскольку вы можете передать значение матрицы непосредственно в y-шкалу:
var line = d3.svg.line()
.interpolate("basis")
.x(function(d, i) { return x(times[i]); })
.y(y);
Создание элементов остается прежним:
group.selectAll(".line")
.data(values)
.enter().append("path")
.attr("class", "line")
.attr("d", line);